简体   繁体   English

React:this.state vs this.setState

[英]React: this.state vs this.setState

Scenario 1: 场景1:

const { foo } = this.state;

Scenario 2: 场景2:

this.setState(({ foo }) => { ... });

is foo guaranteed to be identical between these two cases? 在这两种情况下, foo保证是相同的吗? Or will setState ever run async and return a different value based on other setState s? 或者setState是否会运行异步并根据其他setState返回不同的值?

State might be state when you access the state immediately after using this.setState , as this.setState is async . 使用this.setState后立即访问状态时状态可能是状态,因为this.setStateasync

If you need to compute on basis on the updated state ie ( after this.state is invoked ), you can use the 2nd argument for the method which is a callback that gets triggered after the state changes are committed. 如果需要根据更新的状态进行计算,即(在调用this.state之后),可以使用方法的第二个参数,该方法是在提交状态更改后触发的回调。

this.setState(updateState, () => {
   const { foo } = this.state;

   console.log(foo); // updated foo
});

function updatedState({ foo }) { 
    // you can be sure that `foo`
    // is from the previous state 
    // before setState is called
}

As the React docs mention: 正如React文档所述

setState() does not always immediately update the component. setState()并不总是立即更新组件。 It may batch or defer the update until later. 它可以批量推迟更新或推迟更新。 This makes reading this.state right after calling setState() a potential pitfall. 这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。 Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. 相反,使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发。

So we can use the second argument of the setState to pass a callback where we execute our logic which depends on having the updated value of foo. 所以我们可以使用setState的第二个参数传递一个回调,我们执行逻辑,这取决于foo的更新值。 However your initial question was whether the value of foo in const { foo } = this.state; 然而,你最初的问题是const { foo } = this.state;的foo值是否为const { foo } = this.state; and the value of foo in this.setState(({ foo }) => { ... }); this.setState(({ foo }) => { ... });的foo值this.setState(({ foo }) => { ... }); was the same. 是一样的。

In order check this we can compare executing a setState followed by this.state.foo and a setState followed by another setState (the second one will just log the value of foo instead of mutating it). 为了检查这一点,我们可以比较执行一个setState后跟this.state.foo和一个setState后跟另一个setState (第二个只记录foo的值而不是改变它)。 Please refer to the following snippet: 请参阅以下代码段:

 class Example extends React.Component { constructor() { super(); this.state = { foo: 0, boo: 0 } } handleClickSetState = () => { this.setState(({foo}) => ({foo: foo+1})); this.setState(({foo}) => console.log("inside setState. foo: ", foo)); } handleClickState = () => { this.setState(({boo}) => ({boo: boo+1})); console.log("outside setState. boo: ", this.state.boo) } render() { return <React.Fragment> <button onClick={this.handleClickState}>Test state</button> <button onClick={this.handleClickSetState}>Test setState</button> </React.Fragment> } } ReactDOM.render(<Example />, document.getElementById("root")); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"></div> 

As we can see the "state case" lags behind by 1, which we would expect since setState is async (and we didn't use the second argument of setState ). 正如我们所看到的那样,“状态情况”滞后于1,我们期望这是因为setState是异步的(我们没有使用setState的第二个参数)。 However the "setState case" shows that the correct value is always shown, even if we don't utilize the second argument callback in setState. 但是,“setState case”表示始终显示正确的值,即使我们不在setState中使用第二个参数回调。

In conclusion const { foo } = this.state; 总之const { foo } = this.state; will always give you the immediate value of foo, regardless of pending state merges, while this.setState(({ foo }) => { ... }); 永远会给你foo的直接值,无论挂起状态合并,而this.setState(({ foo }) => { ... }); seems like it will first finish pending updates before executing the callback, which means foo will always have the most recent value. 看起来它会在执行回调之前首先完成挂起的更新,这意味着foo将始终具有最新的值。

setState is async, and pulling values off state to use in setState is a potential source of bugs. setState是异步的,并且将值关闭以在setState使用是潜在的错误来源。 setState can take multiple arguments. setState可以使用多个参数。 It can take just a new state, a callback that takes old state + props and returns new state, new state and a function to run after setting new state, or a combination. 它可以只需要一个新的状态,一个回调,它接受旧状态+道具并返回新状态,新状态和一个在设置新状态或组合后运行的函数。 Example: 例:

this.setState(
  // function taking previous state + props,
  // which should return updated state.
  // this could also just be an object with
  // the new state, if you don't need to rely
  // on previous state.
  (previousState, props) => {
    if (previousState.something) {
      return { something: somethingElse }
    } else {
      return { something: anotherThing }
    }
  }, () => {
    // safe to use new state here,
    // since state has been updated.
    // but it's recommended to use
    // componentDidUpdate instead!
  })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM