React/最適化/Lesson 18
useTransition / useDeferredValue — 重い更新をバックグラウンドへ
30分·theory
このチャプター
1/2
TypeScript
useTransition / useDeferredValue — 重い更新をバックグラウンドへ
💡 なぜ学ぶのか? — 入力がカクつく理由
🎯
検索ボックスで素早くタイピングすると入力が詰まる現象 — 値の変更が重いフィルタリング・レンダリングと同じ優先度で処理されるため。
💼
useTransition は「この state の更新は急がない — 入力の方が重要だ」と React に伝えます。
⚡
React は入力の更新を先に表示し、重い更新はバックグラウンドに譲渡します → 入力がスムーズになります。
🔗
useDeferredValue は同様の効果を「値」単位で実現します — 遅延された値だけを重い子コンポーネントに渡すパターンです。
📈
かつてデバウンスやスロットルで対処していた UX の問題を、React がタイムスライシングで解決します。
🏢 실무에서는
検索オートコンプリート、大きなリストのフィルタリング、チャートデータの変更、重いマークダウンプレビュー — これらはすべて useTransition の領域です。ユーザーは「入力がスムーズだ」とだけ感じ、重い処理はバックグラウンドで自動的に描画されます。
useTransition · useDeferredValue · startTransition
1. useTransition — 「この setState は後回し可能」と示す
- ▸
startTransition(fn)内の setState は後回し可能としてマークされます。 - ▸React はより緊急な更新(入力・クリック)があれば、そちらを先に処理します。
- ▸
isPendingで後回しにされた更新が進行中かどうかを確認 → スピナーを表示。
2. useDeferredValue — 値を「一拍遅れのコピー」として扱う
- ▸
queryは即時更新(入力が滑らか)。 - ▸
deferredQueryは React に余裕があるときに追従します。 - ▸
HeavyResultsが deferredQuery で重い処理をしても、入力には影響しません。
3. いつどちらを使う?
4. startTransition — フック不要でも呼び出せる
5. 注意点
- ▸処理が本当に重い場合(1秒以上)は useTransition だけでは不十分。Web Worker などが必要になります。
- ▸fetch 自体は後回しにできません — fetch のレスポンスを処理する setState のみ後回し可能です。
- ▸あくまで「スケジューリングのヒント」— React が実際に後回しにできるときのみ後回しにします。
💡 💡 useTransition / useDeferredValue 実践の5つのポイント
1. 入力は即時、結果は後回し — 最もよくあるパターン
2. isPending で進行状態を表示
3. fetch のレスポンス処理は後回し可能、fetch 自体は後回し不可
4. useDeferredValue は「受け取った値」単位、useTransition は「自分が呼び出す」単位
親から受け取った props が頻繁に変わり、それを受け取る子が重い場合は useDeferredValue を使います。
5. デバウンスの部分的な代替であり、完全な代替ではない
useTransition はタイムスライシング、デバウンスは呼び出し自体を減らします。通常はどちらか一方を選び、状況に応じて使い分けます。
⚡ 実際に試してみる — startTransition のフロー
緊急な更新と後回し可能な更新の優先順位をシミュレーションします。
✏️ JS 코드
📟 コンソール出力
▶ 実行ボタンを押してください
⚠️ ブラウザのサンドボックスで実行 — console.log()のみ対応、alert/fetchは不可
確認クイズ
検索ボックスへの入力中、オートコンプリートのレンダリングが重くて入力がカクつきます。最も適切なツールは何ですか?
先に読むとよい概念: Zustand — 今日のトップティアグローバルステート