Reactjs-setState 前一个状态为第一个参数,props 为第二个参数

IT技术 javascript reactjs setstate
2021-03-26 12:56:06

我在这篇官方文章中阅读了以下几行:

this.props并且this.state可能会异步更新,您不应该依赖它们的值来计算下一个状态。

任何人都可以通过举例向我解释以下代码试图实现的目标。

 this.setState((prevState, props) => ({
  couter: prevState.counter + props.increment
}));

我指的是reactjs React.js的这个官网

3个回答

他们说你应该这样做而不是下面的例子。

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

如果您像这样访问,他们无法确保状态将具有正确的值,因为setState()将异步发生,其他更新可能会发生并更改该值。如果你要根据之前的状态计算状态,你必须确保你有最后一个和最新的值,所以他们让setState()接受一个用prevStateprops调用的函数,这样你就可以有正确的值来更新您的状态,如下例所示。

 // Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

为了补充布鲁诺的答案,上面的正确函数称为函数。React 在称为不变性的方面很重要,这意味着如果可能的话,每个声明的值都不应该改变其原始声明。该函数中的变量在您传入之前不是您的实际props和状态,这意味着在 javascript 函数堆栈(排队同步和异步调用的线程)上,值和对属性的引用将以不同方式存储,从而产生不确定性在“错误”情况下的value。

谢谢。函数是无状态的,而类不在 Reactjs 中?
2021-06-15 12:56:06

React 可以将多个 setState() 调用批处理为单个更新以提高性能。

因为this.propsthis.state可能会异步更新,所以您不应该依赖它们的值来计算下一个状态。

来自https://reactjs.org/docs/react-component.html#setstate

setState() 将组件状态的更改加入队列,并告诉 React 该组件及其子组件需要使用更新后的状态重新渲染。

将其setState()视为更新组件请求而不是立即命令。为了更好的感知性能,React 可能会延迟它,然后一次更新多个组件。React 不保证立即应用状态更改。

举例理解

这个概念可能很难理解,特别是为什么它会导致问题,所以我写了一个例子来显示发生的错误:

/* Imagine props and states is the same as this.props and this.state */
var state = { counter: 0 } ; var props = { } ;

/* Our fake implementation of react setState */
var setStatesToRun = []
function setState(myFunction) { setStatesToRun.push(myFunction); }

/* Our fake implementation of react batch update */
function batchRunStateUpdates() {
  propsLocal = props
  stateLocal = state

  f1 = setStatesToRun.pop()
  newState = f1(stateLocal, propsLocal)  // Will run increment by 3
  console.log(newState) // newState: { counter: 3 }
  console.log(state) // state: { counter: 0 }

  f2 = setStatesToRun.pop()
  newState = f2(newState, propsLocal) // Will run increment by 2
  console.log(newState) // newState: { counter: 2 }
  console.log(state) // state: { counter: 0 }

  // ... get the next setState function loop

  console.log("Will update global state")
  state = newState  
  console.log(state) // state: { counter: 2 } // WRONG!
}

console.log(setStatesToRun) // []

// Right
setState((prevState, props) => { counter: prevState.counter + 3 });

// WRONG, using state (this.state)
setState((prevState, props) => { counter: state.counter + 2 });

console.log(setStatesToRun) // [func, func]

batchRunStateUpdates();

在顶部,我们有一些 React 方法的假版本。这些过于简化,但有助于解释会发生什么。

然后,我们像在 React 中一样使用 setState。一种用法是对的,另一种是错误的。

注意最终的全局状态应该是state: { counter: 5 },但是由于我们不尊重 React 的建议,我们得到了state: { counter: 2 }

您可以在https://jsfiddle.net/oniltonmaciel/g96op3sy/ 中使用此代码