小编典典

使用React useState()钩子更新和合并状态对象

reactjs

我发现React Hooks文档的这两部分有些令人困惑。使用状态挂钩更新状态对象的最佳实践是哪一种?

想象一下要进行以下状态更新:

INITIAL_STATE = {
  propA: true,
  propB: true
}

stateAfter = {
  propA: true,
  propB: false   // Changing this property
}

选项1

使用React Hook的文章中,我们可以做到:

const [count, setCount] = useState(0);
setCount(count + 1);

所以我可以做:

const [myState, setMyState] = useState(INITIAL_STATE);

然后:

setMyState({
  ...myState,
  propB: false
});

选项2

钩子参考中我们可以得出:

与类组件中的setState方法不同,useState不会自动合并更新对象。您可以通过将函数更新程序形式与对象传播语法结合使用来复制此行为:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

据我所知,两者都可以。那么区别是什么呢?最佳做法是哪一种?我应该使用传递函数(选项2)来访问以前的状态,还是应该简单地使用扩展语法访问当前状态(选项1)?


阅读 2579

收藏
2020-07-22

共1个答案

小编典典

这两个选项都是有效的,但是就像setState在类组件中一样,在更新从已经处于状态的东西派生的状态时,需要小心。

例如,如果连续更新两次计数,则如果不使用更新状态的函数版本,它将无法按预期工作。

const { useState } = React;



function App() {

  const [count, setCount] = useState(0);



  function brokenIncrement() {

    setCount(count + 1);

    setCount(count + 1);

  }



  function increment() {

    setCount(count => count + 1);

    setCount(count => count + 1);

  }



  return (

    <div>

      <div>{count}</div>

      <button onClick={brokenIncrement}>Broken increment</button>

      <button onClick={increment}>Increment</button>

    </div>

  );

}



ReactDOM.render(<App />, document.getElementById("root"));


<script src="https://unpkg.com/react@16/umd/react.development.js"></script>

<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>



<div id="root"></div>
2020-07-22