再レンダリングを制御して最適化することでパフォーマンス改善
🤔 長くなってきたので書き終わったら別のscrapboxにまとめよう
再レンダリングが起きる3つのパターン
1. State が更新されたコンポーネント
2. Props の値が変更されたコンポーネント
3. 再レンダリングされたコンポーネント配下のコンポーネント全て
3の 再レンダリングされたコンポーネント配下のコンポーネント全て とは
以下だと、 ルートコンポーネントの App.jsx がStateを更新した時、全てのコンポーネントが(Child1-4)再レンダリングされる
Child1.jsx なら 2と3も再レンダリング
https://gyazo.com/6815de626182b5f4e090382a282b3710
レンダリングの最適化
さっきの例で、App の Stateが更新されても child 1-4 は再レンダリングさせたくない場合
1. memo化する
Reactでは コンポーネント・変数・関数などの再レンダリング時の制御をするにはメモ化をする
メモ化とは:前回の処理結果を保持しておくことで処理を高速化する技術。必要な時だけ再計算することで不要な処理を省ける。
やり方: 今回はコンポーネントのメモ化をする。 memo は コンポーネント関数全体を () で囲むだけで使用できる
code:.js
const コンポーネント = memo(() => {});
code: .jsx
// before
export const App = () => {
return (
<div>
< />
</div>
);
};
// after
export const App = memo(() => {
return (
<div>
< />
<div/>
);
});
これを書くと、 memoで囲まれた コンポーネントは Props や Stateに 変更がない限り再レンダリングされなくなる。
今回の場合、親とchild1-4すべてに書くと、親でstateやpropsに変更があれば、親だけが再レンダリングされる
2. useCallback
コンポーネントをmemo化していても再レンダリングされてしまう原因は、関数の再生成
例
親 で State を持ち、それを子 にpropsとして渡してる時:親の関数でstateが変更されたら、子に渡されるpropsも変わったと判定して、子も再レンダリングされる
そこで useCallback を使う
code:.js
export const App = memo(() => {
const onClickReset = useCallback(() => { //✅ ここでuseCallbackを使う
setNum(0);
}, []);
return (
<>
<button onClick={onClickButton}>ボタン</button>
<p>{num}</p>
<Child1 onClickReset={onClickReset} /> // ここで子に渡してる
<Child4 />
</>
);
});
つづき: p.170- ~