Suspenseコンポーネント
データの受け取り状態を検知できるコンポーネント
1 2 3 |
<Suspense fallback={<待機中に表示させたいコンポーネント />}> <任意のコンポーネント /> </Suspense> |
任意のコンポーネント(非同期処理があるもの)が返ってくるまで待機中に表示させたいコンポーネントをfallbackで指定できます。
また、Suspense自体はネストもできるので「あるコンポーネントはこのデータロードが終わるまで出す」、「さらに別コンポーネントは別途待つ」などの記述もできたりします。
メリット
「ローディングコンポーネント」と「任意のコンポーネント」のロジックを分離できるので良い。
Suspense on Server
非同期で処理を待っている間は部分的にレンダリングできる。SSRが重くならない。
今だったらISR(アクセスがあるごとにインターバルを置いて新しいサイトを生成する技術)でレンダリングする戦略はある。
Streaming Server Rendering with Suspense
準備されたコンポーネントからブラウザに描画していく。描画の遅いコンポーネントがあれば他のコンポーネントの描画もそれに引きづられて遅くなってしまう。
各コンポーネントを並列で描画できるようになる。
今までは全てのコンポーネントが描画されるまではクリックなどのイベントハンドラも実行することができなかったが、あるコンポーネントの描画が完了するまで待たなくても別コンポーネントのクリックなどをできるようになった。
React Server Component
サーバー内でしか実行されない。
SPAとSSRを共存できる機能。SPAで表示させたいものをclient.jsで指定し、SSRで表示させたいものはserver.jsというファイルを作ってserver.js側でclient.jsをインポートして使う。
メリット
- クライアント側にライブラリなどがバンドルさせなくても良くなる。(バンドルサイズは全てにおいて悪だしできるだけ小さくした方が良い)
- データソースにダイレクトにアクセスできる。(API経由で呼び出さなくてもよくなる。)
制約
- server.js内でしかこの機能は使えない。
- useStateは使えない。
ステート更新
automatic batching
従来だと、stateを更新するたびに再レンダリングが行われることになる。それがstateが何度更新されようとレンダリングは1度だけ行うようにするなどをしてくれる機能。正確に言えば、前からauto batchingの機能自体はあったのですが、18からはpromiseなどにも対応されました。(17までは対応していなかった。)
1 2 3 4 5 |
setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); // React will only re-render once at the end (that's batching!) }, 1000); |
複数stateが更新される場合は、最後のstateが更新された場合のみ再レンダリングを実行するというような仕様に変更になっています。
ユースケース
axiosなどでAPIを実行して取得した処理結果などでstateを複数更新する場合でも一度しか再レンダリングが発生しなくなります。
コンカレントモードを実現するための新APIが追加される。
startTransition
React17まではstateの更新に優先順位をつけることはできなかった。優先度が高い処理を低い処理に割り込ませて実行させるというコンカレント(並列計算)な実行がReact18で可能になりました。
startTransitionで指定するstateは緊急性がないstateとみなすことができ特定処理のパフォーマンスを上げることができる。
例
フォームに入力した値を元にフィルターする処理があるとしたら、キー入力の状態更新の優先度を上げて、フィルターは少し優先度を下げるなど。
実装例
1 |
const [isPending, startTransition] = useTransition() |
isPending
trueなら優先度が高いstateが更新されていて、優先度が低いstateがまだ更新されてないことを指します。falseなら全てのstateが更新されている状態を指します。
例えば、以下のようにinputとupdateValueという状態があったとしたらstartTrasitionを指定している状態(updateValue)は更新を遅延させることが可能です。
1 2 3 4 |
const update = (e) => { setInput(e.target.value) startTransition(() => setUpdateValue(e.target.value)) } |
useTransition
useDeferredValue
遅延させる。
この記事へのコメントはありません。