Reputation: 89
I am making the Recipe Box project from Free Code Camp. I have an event handler that is supposed to send an object that contains an array property made up of ingredients up to a parent component which will display the items in the array. The problem is, when I first click the button that fires the handler, it sends an empty array even though there are ingredients entered by the user, and the second time I click it, it sends the ingredients from the previous button click, and it goes on like this every time the button is clicked. How can I fix this?
Method in question:
handleSubmit() {
let ingredientsArrayUpdater = (ingredient) => {
this.setState(prevState => ({
ingredientsArr: [
...prevState.ingredientsArr,
ingredient
]
}))
}
let splitUserInput = this.state.ingredients.split(',');
splitUserInput.map(ingredient => {
return(
ingredientsArrayUpdater(ingredient.trim())
)
});
let recipeObject = {
recipeName: this.state.recipe,
ingredientList: this.state.ingredientsArr,
idNumber: Math.floor((Math.random() * 100000000) + 1)
}
this.props.addRecipe(recipeObject);
}
Code for button that triggers event handler:
<button onClick={e => {this.handleSubmit()}}
className="btn btn-outline-success btn-sm">
Add Recipe
<i className="fas fa-plus"></i>
</button>
Here is the github repository to see all the components. Index.js is the parent component.
https://github.com/EsTrevino/recipe-box-project/tree/master/src
Upvotes: 3
Views: 5104
Reputation: 5198
First, you aren't updating the state when you think you are. You also aren't waiting for the updated state, after you call setState
. I'm not sure about all that you're trying to achieve in this method, but a start is:
handleSubmit() {
let splitUserInput = this.state.ingredients.split(',');
let newArray = this.state.ingredientsArr.concat(splitUserInput.map(a => a.trim()));
this.setState({ingredientsArr: newArray});
let recipeObject = {
recipeName: this.state.recipe,
ingredientList: newArray,
idNumber: Math.floor((Math.random() * 100000000) + 1)
}
this.props.addRecipe(recipeObject);
}
That's "cheating" using what we know the state will be updated to. You can also use a callback for setState
to be more unidirectional.
handleSubmit() {
let splitUserInput = this.state.ingredients.split(',');
let newArray = this.state.ingredientsArr.concat(splitUserInput.map(a => a.trim()));
this.setState({ingredientsArr: newArray}, () => {
let recipeObject = {
recipeName: this.state.recipe,
ingredientList: newArray,
idNumber: Math.floor((Math.random() * 100000000) + 1)
}
this.props.addRecipe(recipeObject);
});
}
Same difference, IMO.
Upvotes: 1