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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50837670/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:17:59  来源:igfitidea点击:

Reactjs-setState previous state is the first argument, props as the second argument

javascriptreactjssetstate

提问by QuickCoder

I have read in this official article these lines:

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

this.propsand this.statemay be updated asynchronously, you should not rely on their values for calculating the next state.

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

Can anyone please explain to me what the following code is trying to achieve by giving an example.

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

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

I am referring to this official website of reactjs React.js

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

回答by Bruno Mazzardo

They say you should do like that instead of the below example.

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

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

They can't assure the state will have the correct value if you access like this because setState()will happen asynchronously, other updates could occur and change the value. If you are going to calculate the state based on the previous state, you have to make sure you have the last and most up to date value, so they made setState()accept a function that is called with prevStateand props, so you can have the correct value to update your state, like the example below.

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

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

回答by lehmanad1

To add to Bruno's answer, the correct function above is called a purefunction. React is big on something called immutabilitywhich means that every declared value should never be changed from its original declaration if possible. The variables in that function aren't your actual props and state until you pass them in, which means on the javascript function stack (the thread that queues up sync and async calls) the values and references to properties will be stored differently, creating uncertainty of what the value will be in the "wrong" case.

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

回答by Onilton Maciel

React may batch multiple setState() calls into a single update for performance.

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

Because this.propsand this.statemay be updated asynchronously, you should not rely on their values for calculating the next state.

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

And from https://reactjs.org/docs/react-component.html#setstate:

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

setState()enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state.

Think of setState()as a requestrather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.

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

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

Understanding with a example

举例理解

This concept may be hard to understand and specially why it could cause issues, so I wrote an example that show an error happening:

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

/* 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();

At the top we have some fake versions of React's methods. Those are overly simplified, but help explain what happens.

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

Then, we use setState the same way we do in React. One usage is right, the other is wrong.

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

Notice the final global state should be state: { counter: 5 }, but because of how we didn't respect React's recommendations we got state: { counter: 2 }

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

You can play with this code in https://jsfiddle.net/oniltonmaciel/g96op3sy/

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