Real world usage of setState with an updater callback instead of passing an object in React JS

扶醉桌前 提交于 2019-12-05 20:48:40

setState is only concerned with component state consistency, not server/client consistency. So setState makes no guarantees that the component state is consistent with anything else.

The reason an updater function is provided, is because state updates are sometimes delayed, and don't occur immediately when setState is called. Therefore, without the updater function, you have essentially a race condition. For example:

  • your component begins with state = {counter: 0}
  • you have a button that updates the counter when clicked in the following way: this.setState({counter: this.state.counter +1})
  • the user clicks the button really fast, so that the state does not have time to be updated between clicks.
  • that means that the counter will only increase by one, instead of the expected 2 - assuming that counter was originally 0, both times the button is clicked, the call ends up being this.setState({counter: 0+1}), setting the state to 1 both times.

An updater function fixes this, because the updates are applied in order:

  • your component begins with state = {counter: 0}
  • you have a button that updates the counter when clicked in the following way: this.setState((currentState, props) => ({counter: currentState.counter + 1}))
  • the user clicks the button really fast, so that the state does not have time to be updated between clicks.
  • unlike the other way, currentState.counter + 1 does not get evaluated immediately
  • the first updater function is called with the initial state {counter: 0}, and sets the state to {counter: 0+1}
  • the second updater function is called with the state {counter: 1}, and sets the state to {counter: 1+1}

Generally speaking, the updater function is the less error-prone way to change the state, and there is rarely a reason to not use it (although if you are setting a static value, you don't strictly need it).

What you care about, however, is that updates to the state don't cause improper data (duplicates and the like). In that case, I would take care that the updates are designed so that they are idempotent and work no matter the current state of the data. For instance, instead of using an array to keep the collection of messages, use a map instead, and store each message by key or hash that is unique to that message, no matter where it came from (a millisecond timestamp may be unique enough). Then, when you get the same data from two locations, it will not cause duplicates.

I'm not an expert in React by any means and have only been doing it for two months only, but here's what I learned from my very first project in React, which was as simple as showing a random quote.

If you need to use the updated state right after you use setState, always use the updater function. Let me give you an example.

// 
 handleClick = () => {
   //get a random color
   const newColor = this.selectRandomColor();
   //Set the state to this new color
   this.setState({color:newColor});
   //Change the background or some elements color to this new Color
   this.changeBackgroundColor();
}

I did this and what happened was that the color that was set to the body was always the previous color and not the current color in the state, because as you know, the setState is batched. It happens when React thinks it's best to execute it. It's not executed immediately. So to solve this problem, all I have to do was pass this.changeColor as a second argument to setState. Because that ensured that the color I applied was kept up to date with the current state.

So to answer your question, in your case, since you're job is to display the message to the user as soon as a new message arrives, i.e use the UPDATED STATE, always use the updater function and not the object.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!