根据渲染函数中的前一个设置状态

Set state based on previous one in render function

我最近阅读了 react.js documentation 并发现根据以前的状态值设置状态不一致。这是那段代码:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

我认为这种设置 state 的方式 () => this.setState({ count: this.state.count + 1 }) 是错误的,您应该为此目的使用回调。所以我提出了 PR,我在其中添加了对先前状态的回调函数的使用,但它已被弃用,因为

The callback version is useful when you're not certain what the captured value of state is.

我真的不喜欢你不确定解释的哪一部分,有人可以解释为什么这样做 () => this.setState({ count: this.state.count + 1 }) 设置状态是正确的。

提前致谢。

使用return函数

通过在此处传递函数,您将始终可以访问之前的状态。

this.setState((prevState) => ({ count: prevState.count + 1 }))

请注意,您还可以添加道具作为第二个参数。

如果您想阅读有关此回调的更多信息,请查看 this article。介绍的很详细。

在您当前的示例中,您将默认状态设置为 { count: 0 },您 "safe" 要做 setState({ count: this.state.count + 1 }) 因为当您第一次更新状态时,0 + 1将产生有效结果。

class App extends React.Component {
  state = { count: 0 }
  render() {
    return (
      <div>
         <p>You clicked {this.state.count} times</p>
         <button
           onClick={() => this.setState({ count: this.state.count + 1 })}
         >
           Click me!
         </button>
      </div>
    )
  }
}
ReactDOM.render(
  <App />,
  document.getElementById("app")
)
<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="app"></div>

但是,我们假设 state 的某些部分的初始值不是 0,因此调用 this.state.count + 1 可能会产生无效结果。这是您需要 callback 版本的地方,因为:

you're not certain what the captured value of state is.

class App extends React.Component {
  state = { count: null }
  render() {
    const handleClick = () => {
      this.setState((prevState) => {
        // count is initially `null`, so 
        // `null + 1` could yield an undesired result
        if (!Number.isInteger(prevState.count)) {
          return { count: 1 }
        }
        return { count: prevState.count + 1 }
      })
    }
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={handleClick}>
          Click me!
        </button>
      </div>
    ) 
  }
}
ReactDOM.render(
  <App />,
  document.getElementById("app")
)
<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="app"></div>

这只是一个例子,但你明白了。


您的 PR 很可能被拒绝,因为文档中的示例是正确的,假设它用于 "safe" 通过执行 this.setState({ count: this.state.count + 1 }) 更新您的状态的相同上下文。

这是文档:

两种更新方式state都是正确的,应该在适当的时候使用。正如您在第二个示例中看到的,如果想在更新 state 之前进行一些检查,"callback option" 将是更好的解决方案。

不过,文档中的示例是正确的,如果它使用 "callback option" 则不会产生任何好处。