Open3
Reactレンダリング
どんな時に再レンダリングされるか?
- stateが更新されたコンポーネント
- propsが変更されたコンポーネント
- 再レンダリングされたコンポーネントの配下の子要素
レンダリングが不要な部分にも起きまくってしまうと重くなるので、最適化する必要がある
親がレンダリングされても、子要素に変更がなければ子要素は再レンダリングされないようにする方法
memoでコンポーネントを全て囲ってしまう
ChildArea.jsx
export const ChildArea = memo((props) => {
const { open, onClickClose } = props;
console.log("ChildAreaがレンダリングされた");
return (
<>
{open ? (
<div>
<p>子コンポーネント</p>
<button onClick={onClickClose}>閉じる</button>
</div>
) : null}
</>
);
});
基本的に全てmemoで囲ってしまえばいいか
propsに関数を渡すと、更新の度に再生成され、同じ値を渡していても再レンダリングが起きてしまう
App.js
export const App = () => {
//テキストが入力されると
const onChangeText = (e) => setText(e.target.value);
const onClickOpen = () => setOpen(!open);
//この関数も再生成されて、
const onClickClose = () => setOpen(false);
return (
<div className="App">
<input value={text} onChange={onChangeText} />
<br />
<br />
<button onClick={onClickOpen}>表示</button>
{/* 以下のコンポーネントが毎回再レンダリングされてしまう */}
<ChildArea open={open} onClickClose={onClickClose} />
</div>
);
処理が毎回変わらないなら使いまわすという処理をするために、
useCallbackで関数を囲む
第2引数には監視するものを指定する。以下のコードではsetOpenを指定しているが、これは固定で変化はしないので実質[]を指定しているのと同じ。
基本的にはuseCallbackで囲った関数内で使用する「変数」「関数」を[]に指定してあげれば正しい動作を保ったまま最適化できる。
before
const onClickClose = () => setOpen(false);
after
const onClickClose = useCallback(() => setOpen(false), [setOpen]);