React memo, callback
by Natsumi Chiba
React アプリで 無駄な再レンダリングを減らしてパフォーマンスを改善する方法
React.memo / useCallback / useMemo を学びます
React のレンダリングの仕組み
React はコンポーネントが更新されると:
jsx → React要素に変換
その後差分を比較し DOM を更新
という流れで処理します。
見た目が変わらなくてもレンダリングだけ行われることがある というポイントが重要。
無駄なレンダリングとは?
以下のような 何も変化していないのに再レンダリングが走る状態 を指します:
親コンポーネントが更新されたとき
→ その下の子コンポーネント全てが再レンダリングされる
→ 見た目が変わらなくてもレンダリングだけ実行されてしまう
React.memo / useCallback / useMemo : 無駄なレンダリングを止める方法
| 機能 | 何をメモ化する? | 目的 | |
|---|---|---|---|
| React.memo | コンポーネント | 再描画を抑える | |
| useCallback | 関数 | 関数の再生成を抑える | |
| useMemo | 値 | 重い計算の再計算を抑える |
| 課題 | 解決策 |
|---|---|
| 親の再レンダリングで子も無駄に再レンダリングする | React.memo で止める |
| props の参照が変わって更新と判定されてしまう | useMemo / useCallback で参照を固定する |
「メモ化 (Memoization)」とは
メモ化 とは一度計算した値や結果を覚えておいて、再利用する仕組みです。
つまり、同じ計算や同じ処理を何度もやらずに済むようにするための手法です。
React でパフォーマンス改善が必要な理由
React は state や props が変わるとコンポーネントの再レンダリングを行います。
これを何も考えずに行うと、処理が重くなる場合があります。
不要な再レンダリングを減らして アプリを速く・軽くする のが目的。
React.memo
コンポーネントを メモ化して再レンダリングをスキップ できます。
props が変わらなければ再レンダリングをスキップする
親の更新があっても子を止められる
使うタイミング
子コンポーネントが頻繁に再レンダリングされる
でも props は変わらない
→ こういうケースで使うと効果あり
const Child = React.memo(props => {
return <p>{props.value}</p>
});
React.memo 単独の落とし穴
ただし React.memo だけでは不十分なケースがあります:
親コンポーネントで関数やオブジェクトを定義すると
→ 親が再描画された瞬間に 参照が変わってしまい
→ React.memo は更新ありと判断してしまう
const onClick = () => {}; // 親が再描画されるたび新しく作られる
const data = {a:1}; // これも毎回新しいオブジェクト
<MemoizedChild onClick={onClick} data={data} />
この場合、React.memo の意味がなくなります
参照を変えない方法
こういう時は 参照が変わらないようにメモ化する必要があります:
✔️ useCallback → 関数をメモ化
✔️ useMemo → オブジェクト / 計算結果をメモ化
これで React.memo が正しく動くようになります
useCallback
関数をメモ化 する React Hooks です。
レンダリングのたびに関数が新しく作られるのを防ぎます。
使うタイミング
React.memo と一緒に使うと効果が大きい!
→ 子コンポーネントに関数を渡しているとき、再レンダリングを防げます。
const handleClick = useCallback(() => {
console.log("Clicked!");
}, []);
✔️「[]」が空 → 初回だけ関数を作る
✔️ 依存配列に値を入れると、その値が変わったときだけ新しい関数を作ります。
useMemo
値の計算結果をメモ化 する React Hooks です。
重い計算結果を再利用することでパフォーマンス改善できます。
使うタイミング
値の計算が重いとき
減らせる再計算があるとき
const doubled = useMemo(() => count * 2, [count]);
→ count が変わったときだけ再計算します
🔍注意ポイント
これらの仕組みは 無駄な再レンダリングを減らすのに有効 だけど
→ 使えば絶対 速くなるわけではない!
→ 計測して必要なところだけに使うべき