1. ホーム
  2. javascript

[解決済み] React useState()フックによるステートオブジェクトの更新とマージ

2023-03-05 21:56:28

質問

React Hooksのドキュメントで、この2つの部分が少し混乱しています。stateフックを使用してstateオブジェクトを更新するためのベストプラクティスはどちらでしょうか?

次のような状態の更新を行いたいとします。

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};
});

私の知る限りでは、どちらも動作します。では、何が違うのでしょうか?どちらがベストプラクティスなのでしょうか?前の状態にアクセスするためにpass the function (OPTION 2)を使うべきか、それとも単にspread syntax (OPTION 1)で現在の状態にアクセスすべきでしょうか?

どのように解決するのですか?

どちらのオプションも有効ですが setState の場合と同様に、すでに状態になっているものから派生した状態を更新するときには注意が必要です。

例えばカウントを2回連続で更新する場合、状態を更新する関数版を使用しないと期待通りに動作しません。

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>