13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React学習ログ No.12

Posted at

React Stateの更新における prev に関する整理

1. 値によるステート更新の限界

useStateフックのセッター関数(例: setCount)に、
ステートの値を直接用いた式を渡す形式(値による更新)には、
意図しない結果を生じる可能性がある

例: カウンターの複数回更新

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

const handleIncrement = () => {
  // countが 0 のとき
  setCount(count + 1); // 0 + 1
  setCount(count + 1); // 0 + 1
};
// 実行結果: count は 1 、期待値は 2

原因: Stale Stateとバッチ処理

  1. 非同期性とバッチ処理: Reactはパフォーマンス最適化のため、同じイベント内で発生した複数のステート更新を一つにまとめて(バッチ処理)非同期に実行
  2. Stale State: イベントハンドラ実行中の count は、そのコンポーネントがレンダリングされた時点の値を保持している(これをステイル(古い)な値と呼ぶ)。上記の例では、
    2回の setCount 呼び出し時、count の値は常に最初の 0 を参照している

2. 解決策: 関数によるステート更新 (prevの利用)

直前のステートの値に基づいて新しいステートを計算する場合、
セッター関数には値ではなく更新関数を渡す必要がある
この更新関数が受け取る引数が prev(直前のステート)

構文

setState(prev => {
  // prev はその時点でキューにある最新の直前のステート値
  return nextState; 
});

例: カウンターの正確な複数回更新

const handleIncrement = () => {
  setCount(prevCount => prevCount + 1); // 1. prevCount(0) + 1 = 1
  setCount(prevCount => prevCount + 1); // 2. prevCount(1) + 1 = 2
};
// 実行結果: count は 2

prevの動作原理

  • Reactは、関数形式の更新をキューに登録し、
    バッチ処理時にキュー内の関数を順序通りに実行
  • 各更新関数が実行される際、引数(prev)には、
    一つ前の更新が適用された後の最新のステート値が渡される

3. prev利用時の留意事項: 不変性(Immutability)

prevとして渡される値(オブジェクトや配列)は、読み取り専用として扱うべきであり、
直接内容を変更(ミューテート)してはならない

ステートがオブジェクトや配列の場合、prevの値を用いて
新しいオブジェクトや配列を作成し、それを返却する必要がある(不変性の確保

例: オブジェクトの更新

// 間違い: prevをミューテートしている
setPerson(prevPerson => {
  prevPerson.age += 1; // 直接変更 (ミューテーション)
  return prevPerson; 
});

// 正しい: スプレッド構文で新しいオブジェクトを作成
setPerson(prevPerson => ({
  ...prevPerson, // 既存プロパティのコピー
  age: prevPerson.age + 1 // 新しい値
}));

4. まとめ

更新方法 形式 適用条件 理由
関数による更新 setState(prev => ...) 直前のステートに依存して計算する場合。 ステイルステートの問題を回避し、更新の順序性を保証するため。
値による更新 setState(newValue) 直前のステートに依存せず、値を上書きする場合。 ステートに特定の値(例: 'default'0)を直接設定する場合など。
13
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?