上級React開発者がHooksについて考えるべきこと
多くの開発者は、Reactがどのようにレンダリングされるかを理解せずにHooksを学びます。これが混乱の原因となります。Hooksをマスターするには、5つの核となる責務を理解する必要があります。
• データの保持 • 副作用の実行 • データの共有 • レンダリングの最適化 • スケジューリングの制御
ステートの変化は再レンダリングをトリガーします。再レンダリングのたびに、変数、オブジェクト、関数が再生成されます。この単純な事実こそが、useMemoやuseCallbackが存在する理由です。
Hooksを理解する
ステートと順序 Reactは、コンポーネントのFiberに紐付けられた連結リスト内にステートを保存します。これが、条件分岐やループの中でHooksを呼び出せない理由です。Reactは、正しいステートを見つけるために呼び出しの順序に依存しています。
バッチ処理の実態 setStateを呼び出すと、Reactは更新をスケジュールします。値は即座に変更されるわけではありません。そのため、値をセットした直後にステートをログ出力しても、古い値が表示されます。古いデータ(stale data)を避けるために、常に関数型の更新パターンを使用してください。
- 良くない例: setCount(count + 1)
- 良い例: setCount(prev => prev + 1)
useEffectのメンタルモデル useEffectをライフサイクルメソッドのように扱うのはやめましょう。APIやWebSocketなどの外部システムとコンポーネントを同期させるために使用してください。
重要:ReactはuseEffectが実行される前に画面を描画します。これにより、エフェクトがUIをブロックしないようになっています。ユーザーが目にする前にDOMを測定する必要がある場合は、useLayoutEffectを使用してください。
useRefの実態 Refは単にDOM要素のためのものではありません。それは永続的な可変コンテナです。Reactはレンダリング間で同じオブジェクト参照を保持します。ref.currentを変更しても再レンダリングはトリガーされません。タイマー、ソケット、または以前の値の保持に使用してください。
メモ化の罠 useMemoは速度を上げるための魔法のボタンではありません。オーバーヘッドというコストが発生します。Reactはキャッシュを保存し、依存関係を比較しなければならないからです。
計算コストがメモ化のコストを上回る場合にのみ、useMemoを使用してください。単純な計算にこれを使用すると、アプリの動作が逆に遅くなります。
Contextはステート管理ではない Contextは依存性の注入(dependency injection)のためのものです。プロップドリリングを避けるのに役立ちます。しかし、Contextの値が変更されると、すべてのコンシューマーが再レンダリングされます。すべてのグローバルステートを一つのProviderに詰め込まないでください。目的ごとにContextを分割しましょう。
高度なパターン • useReducer: 多数の useState を呼び出す代わりに、複雑なステートマシンに使用します。 • startTransition: 重い更新の間も UI の応答性を維持するために使用します。 • useDeferredValue: ユーザーが入力している間に、コストの高い UI 更新を遅延させるために使用します。
ロジックをカスタムフックに切り出すことで、クリーンなコードを書きましょう。1200行ものコンポーネントはメンテナンスが困難ですが、ロジックを担う5つの小さなフックであれば、拡張が容易になります。
出典: https://dev.to/jagadeesh_008/how-advanced-react-developers-should-think-about-hooks-102l