0

I have a total set in my state, initialized to 0.

Here is the function (in is triggered with an input field that gives it the qty parameter in another component):

calculateTotal(qty) {
  if (qty === 1) {
    this.setState({
      total: this.state.total += 250
    })
  }
  else if (qty > 1) {
    this.setState({
      total: qty *= 250
    })
  }
  else {
    this.setState({total: this.state.total})
  }
  console.log(this.state.total);
}
3
  • 1
    What is that bizarre output you get? Commented Aug 7, 2019 at 23:55
  • No. The quantity needs to be multiplied by 250. Commented Aug 8, 2019 at 0:00
  • 1
    this.state.total += 250 is actually "this.state.total = this.state.total + 250". Why are you mutating the original value instead of updating 'total' via setState? Commented Aug 8, 2019 at 0:04

2 Answers 2

4

Since you are calling setState, I'm assuming that your code represents one method of some larger component.

setState is an asynchronous operation so your console.log is probably being called before the component state has been updated. However, if you try to console.log in the component's render method, you'll get more predictable results.

Since you should use setState to update your state and not mutate it directly, you should not do this:

this.state.total += 250

This tries to directly update total, effectively trying to bypass setState. You normally want to do something like this instead:

this.setState({
  total: this.state.total + 250
})

However, this is also incorrect because you want to calculate a new state based on a previous state. To be guaranteed to get the previous state (due to the asynchronous nature of setState) you should do this instead:

this.setState((prevState) => {
  return {
    total: prevState.total + 250
  }
})

Also, this.setState({total: this.state.total}) is not necessary. If you do not want to change the state, simply do nothing.

Finally, when the component's state has been updated, the React framework will then re-render your component. Therefore, try to log total in your component's render method. You should then get the values you expect.

Sign up to request clarification or add additional context in comments.

2 Comments

Great answer. Just a style suggestion, your last snippet can be simplified to this.setState(prevState => ({ total: prevState.total + 250 }))
Totally. For "ES6-ophiles," this is the best syntax! :) <3 ... however, I wanted to show the longer form for clarity. Thanks for showing the alternative.
0

For one you only have to call setState once. Also setState is asynchronous as you stated along with the console log so in order to ensure the log is running after you set the state utilize a callback with setstate

calculateTotal(qty) {
  var total;
  if (qty === 1) {
    total = this.state.total + 250; // total = total + 250
  }
  else if (qty > 1) {
    total = (qty * 250);  // total = qty * 250
  }
  else {
    total = this.state.total;
  }
  this.setState({ total }, () => console.log(this.state.total))
}

2 Comments

Hi there, this reached the output I wanted however it only outputs the previous calculation, perhaps it needs to be in a component did mount?
@TomK Not sure you would have to provide additional code to clarify. Maybe mimic the problem utilizing a react fiddle jsfiddle.net/reactjs/69z2wepo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.