はじめに
こちらの記事の続きです
Effectフック
Effectを利用することでコンポーネントを外部システムに接続し、同期させることができます。
Effectはレンダー自体によって引き起こされる副作用を指定するためのもので、外部システムとの接続がなければ特に利用する必要がありません。
公式にもそのエフェクトは不要かもというドキュメントがあったりします。
Effectは以下のような手順で行われます。
- Effectを宣言する
- コンポーネントがレンダーされるたびにReactは画面を更新し、そのあとでuseEffect内のコードを実行する
- 依存値の配列を指定する
- 依存配列がない場合毎回のレンダー後に実行され、依存配列が空([])の場合マウント時のみ実行される
- 必要に応じてクリーンアップを追加する
指定したすべての依存値が前回のレンダー時と全く同じ場合はエフェクトの再実行をスキップします。
- useEffect
- 戻り値はundefined
- useEffect内で外部APIを呼び出すのはあまり得策ではない
- 外部APIの呼び出しにはuseSWRやTanstack Queryを利用すべき
- 画面が更新された後に実行される
- 遅延が目立つ場合はuseLayoutEffectを利用すべき
- useLayoutEffect
- ブラウザが画面を再描画する前に実行される
- 基本的な利用方法はuseEffectと同じ
- useInsertionEffect
- レイアウトエフェクトが発火する前にDOMに要素を挿入するために利用する
- CSS-in-JSライブラリの作者向け
パフォーマンス関連フック
キャッシュ済みの計算結果を再利用したり、データの変更がない場合の再レンダーをスキップすることでパフォーマンスを向上させることができます。
- useMemo
- レンダー間で計算結果をキャッシュする
- 引数としてキャッシュしたい値を計算する関数と、依存配列を受け取る
- 依存配列を忘れるとレンダー毎に再計算されてしまうので注意
- useCallback
- レンダー間で関数定義をキャッシュする
- useTransition
- stete更新の一部をトランジションとしてマークする
- トランジションが保留中であるかどうかを表すフラグとstate更新をトランジションとしてマークするための関数を返す
- useDeferredValue
- UIの一部の更新を遅延させる
- 遅延させたい値を引数として渡す
useMemoとuseCallbackの使い分け
useMemoは関数の呼び出し結果をキャッシュし、useCallbackは関数自体をキャッシュします。
以下のようにuseMemoを利用して関数をキャッシュすることも可能です。
// useMemoを利用する場合
const handleSubmit = useMemo(() => {
return (orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
};
}, [productId, referrer]);
// useCallbackを利用する場合
const handleSubmit = useCallback((orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
}, [productId, referrer]);
どのレベルからメモ化すべきか
以下でタイムを計測し1ms以上など処理に時間がかかる場合にメモ化するべきです。
console.time();
// 処理
console.timeEnd();
トランジションとは
緊急性の高い更新と高くない更新を区別するためのものです。
ここでいう緊急性の高い更新とはタイプ、クリック、プレスなどユーザ操作を直接反映するものです。
優先度が低く、トランジションさせたいset関数をstartTransistionの中に入れます。
その他のフック
- useDebugValue
- React DevToolsでカスタムフックにラベルを追加できる
- useId
- アクセシビリティ属性に渡すことができる一意のIDを生成する
- useSyncExternalStore
- 外部データストアへのサブスクライブを可能にする
- 可能であればuseStateやuseReducerを使用し、非Reactコードと統合するときにこのhooksを利用する
- useActionState
- フォームアクションの結果に基づいてstateを更新する
- フォームが最後に送信されたアクションによって変化するにで、フォームが送信されていない場合は初期stateが利用される
- Canaryおよびexperimentalチャンネルでのみ利用可能
参考資料