Bhushan Lodha Bhushan Lodha - 24 days ago 5
React JSX Question

Wierd react props error

I have two react components:

var AllMeals = React.createClass({
getInitialState() {
return { meals: [], current_page: 0, total_pages: 0, total_count: 0}
},

componentDidMount() {
$.ajax({
url: '/api/v2/meals',
headers: window.Auth.retrieveData('authHeaders'),
success: (data, status, request) => {
this.setState({ meals: data,
current_page: request.getResponseHeader('X-Page'),
total_pages: request.getResponseHeader('X-Total-Pages'),
total_count: request.getResponseHeader('X-Total')});
}
});
},

render() {
const meals = this.state.meals;
return (
<div>
<MealList meals={meals} />
</div>
)
}
});

module.exports = AllMeals


and

var MealList = React.createClass({
getInitialState() {
console.log(this.props)
return { meals: this.props.meals }
},

handleSubmit(meal) {
$.ajax({
url: 'api/v2/meals',
type: 'POST',
headers: window.Auth.retrieveData('authHeaders'),
data: {name: meal.name, calories: meal.calories, meal_time: meal.meal_time, meal_date: meal.meal_date},
success: (new_meal) => {
newState = this.state.meals.concat(new_meal);
this.setState({ meals: newState })
},
error: (response) => {
console.log(response)
}
})
},

filterMeals(id) {
var newState = this.state.meals.filter((meal) => {
return meal.id != id;
});
this.setState({ meals: newState})
},

handleUpdate(meal) {
var meals = this.state.meals;
$.ajax({
url: `api/v2/meals/${meal.id}`,
type: 'PUT',
data: {name: meal.name, calories: meal.calories, meal_time: meal.meal_time, meal_date: meal.meal_date},
headers: window.Auth.retrieveData('authHeaders'),
success: (new_meal) => {
this.setState({
meals: meals.map(meal => meal.id === new_meal.id ? new_meal : meal)
})
},
error: (response) => {
console.log(response);
}
});
},


handleDelete(id) {
$.ajax({
url: `api/v2/meals/${id}`,
type: 'DELETE',
headers: window.Auth.retrieveData('authHeaders'),
success: (response) => {
this.filterMeals(id);
},
error: (response) => {
console.log(response);
}
});
},

handleSearch(meals) {
this.setState({ meals : [...meals] })
},

render() {
const mealsMarkup = this.state.meals.map((meal) => {
return (
<Meal key={meal.id} {...meal} handleDelete={this.handleDelete.bind(this)} handleUpdate={this.handleUpdate.bind(this)} />
)
});

return (
<div>
<div className="col-lg-9">
<div className="page-header">
<h2>Meals</h2>
</div>
<div className='table-responsive'>
<table className='table'>
<thead>
<tr>
<th>Meal</th>
<th>Calories</th>
<th>Time</th>
<th>Date</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{mealsMarkup}
<MealForm handleSubmit={this.handleSubmit.bind(this)} buttonText='Add Meal' />
</tbody>
</table>
</div>
</div>
<MealFilterForm handleSubmit={this.handleSearch} />
</div>
)
}
});

module.exports = MealList;


Weirdly
this.props.meals
in
MealList
is empty. Yes, I checked if meals array exists on
AllMeals
. What could be wrong?

Answer

I think that you are only using the props in MealList before the Ajax call is done, (getInitialState is not called when re-rendered). You should set the state again when the props change with componentWillReceiveProps() in MealList or use the props directly.

Probably adding something like:

componentWillReceiveProps: function(nextProps) {
  this.setState({
    meals: nextProps.meals
  });
}

should be enough.