Esteban Trevino
Esteban Trevino

Reputation: 89

React Event Handler Button Click Not Working on First Click

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

Answers (1)

Nick
Nick

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

Related Questions