根据当前状态反应setState

时间:2018-07-31 07:09:33

标签: javascript reactjs

如果我想根据当前状态更新状态,我想知道使用哪种setState形式。

React的setState将对象或函数作为参数。据我了解,以下内容无法按预期运行,因为React批次setState

state = {score : 0};

increaseScoreBy2 () {
 this.setState({score : this.state.score + 1});
 this.setState({score : this.state.score + 1});
}

最好使用

increaseScoreBy2 () {
 this.setState(prevState => { return { score: prevState.score + 2 }}});
}

但是,如果我只想一次更新状态,应该使用哪种形式的setState?这是个人喜好吗?还是在基于当前状态更新状态时始终使用函数形式,以避免任何可能的意外行为?

例如,以下代码有什么问题吗?

const newRegions = this.state.regions.map(...)
this.setState({ regions: newRegions });

4 个答案:

答案 0 :(得分:2)

正如您所说,是的,一般的经验法则是“ if the next state depends on the previous state, use an updater function”。

  

[this.setState({ regions: this.state.regions.map(...) })有什么问题吗?

我认为这取决于regions数组中的内容以及您传递给map()的内容。也许回答这个问题的最好方法是问问自己,是否批量更新会引起问题:

const mapFcn = ...
const newState = Object.assign(
  {},
  { regions: this.state.regions.map(mapFcn) },
  { regions: this.state.regions.map(mapFcn) },
);

在某些情况下,这可能不是问题。如果每个区域都是一个字符串,mapFcn = (region) => region.toUpperCase()可能不会引起任何问题。

如果regions是一个对象数组,并且mapFcn的行为类似于“经典”增量示例((region) => ({ ...region, count: region.count + 1 })),则可能是个问题。

答案 1 :(得分:0)

状态需要一些时间来更新,因此在设置状态后立即对状态执行操作不是一个好习惯。这使得在调用setState()之后立即读取this.state可能是一个陷阱。如果完全需要,可以使用状态成功更新后调用的回调函数。这是文档的链接:https://reactjs.org/docs/react-component.html#setstate

答案 2 :(得分:0)

如果更新没有冲突,则与对象更新程序多次调用setState没什么问题:

// works
setState({score: this.state.score + 1})
setState({players: [...this.state.players, 'Jack']})

如果更新冲突,则不应从this.state中获取先前的状态,而应由setState在功能更新程序中将其提供给您:

// works
setState((prevState)=> ({score: prevState + 1}));
setState((prevState)=> ({score: prevState + 1}));

这两个都很好。

出了什么问题,即使您只是依赖于当前状态,也只是使用对象更新程序调用{​​{1}},即使它只是一个调用:

setState

答案 3 :(得分:0)

如果只设置一次也没关系。但是这里有一个超级快速的方法来了解为什么在更新状态时依赖现有状态时更喜欢更新程序函数。

function incrementCounter1(){
  this.setState({ counter: this.state.counter + 1 })
}

function incrementCounter2(){
  this.setState(prevState => { 
    return {counter: prevState.counter + 1 }
  })
}

假设 setState() 的执行延迟了 1 秒。

在那 1 秒内,您调用了 incrementCounter1() 3 次。 每次 this.state.counter 仍为 0,而 setState() 收到 {counter: 1}。 因此,计数器的最终值为 1 - 这是错误的。

现在,如果在 1 秒内调用 incrementCounter2() 3 次,setState() 中的函数不会被调用,直到 React 准备好处理状态更改并且之前的状态更改已被执行。因此,prevState 对象将始终具有最新状态。因此 counter 的最终值为 3 - 这是正确的!