前回:useEffect入門:API連携やタイマー処理など「副次作用」を操る方法では、実行タイミングをコントロールする「副作用」の扱いを学びました。
Reactの素晴らしい点は、データが変われば画面を「自動で」書き換えてくれることです。しかし、アプリが複雑になると、**「本当は書き換えなくていい場所まで、何度も計算し直して重くなる」**という問題が発生します。
2026年現在のReact開発において、アプリを爆速に保つための「賢いサボり方」である useMemo と useCallback を攻略しましょう!
1. なぜ「最適化」が必要なのか?
Reactコンポーネントは、State(状態)が更新されるたびに、関数の中身を上から下まで全部実行し直します。
- 問題1: 毎回「ものすごく重い計算」をやり直すと、動作がカクつく。
- 問題2: 中身が同じ「関数」なのに、再描画のたびに「別物」だと判定されて、子コンポーネントまで連鎖的に描き直されてしまう。
これを防ぐのが、計算結果や関数を「メモ(保存)」しておく仕組みです。
2. useMemo と useCallback の違い
似ていますが、保存する対象が違います。
| フック名 | 保存するもの | 使い所 |
| useMemo | 計算結果(値) | 複雑な計算を使い回したい時 |
| useCallback | 関数自体 | 関数を子コンポーネントに渡す時 |
どちらも、第11回で学んだ useEffect と同じように 「依存配列」 を持ち、「この値が変わった時だけ作り直してね」という指示を出します。
3. 【実践】重い計算を「サボらせる」サンプル
今回は、数字を入力するたびに発生する「重い計算」を useMemo で節約する例を見てみましょう。
第2回の環境で作成した App.jsx を書き換えてください。
App.jsx(最小構成版)
JavaScript
import React, { useState, useMemo } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
// 1. 重い計算のシミュレーション
// useMemo を使わないと、textを入力するたびにこのループが走り、重くなります
const expensiveCalculation = useMemo(() => {
console.log("重い計算を実行中...");
let sum = 0;
for (let i = 0; i < 100000000; i++) { sum += i; } // 擬似的な重い処理
return sum + count;
}, [count]); // count が変わった時だけ再計算する!
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<h1>パフォーマンス最適化</h1>
<p>重い計算の結果: {expensiveCalculation}</p>
<button onClick={() => setCount(count + 1)}>
カウントアップ(計算をやり直す)
</button>
<div style={{ marginTop: '20px' }}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="ここに入力しても計算は走りません"
/>
<p>入力中の文字: {text}</p>
</div>
</div>
);
}
4. コードの解説(JavaScript & React)
JavaScriptのポイント
- ループ処理 (
for):1億回の足し算を行っています。これは現代のPCでも目に見えて時間がかかる処理です。 - 関数の等価性:JavaScriptでは、見た目が同じ関数
() => {}でも、新しく定義されるたびに「メモリ上の住所」が変わるため、Reactは「別の関数になった」と判断します。これを防ぐのがuseCallbackの役割です。
Reactのポイント
- メモ化(Memoization):前回の結果をメモリに保存しておき、必要なときだけ再計算する手法です。
- 依存配列の魔法:
[count]と指定することで、text(入力欄)が変わっても計算をスキップし、前回の結果を使い回しています。
5. 2026年の学び:やりすぎ厳禁!
2026年現在のReact開発において、全ての場所を useMemo で囲むのは推奨されません。
- 理由: メモ化自体にもメモリを消費する「コスト」があるからです。
- 指針: 「明らかに動作が重い」と感じた時や、巨大なリストを表示する時に導入するのがベストです。
まずは「Reactは基本、全部描き直す」「重い時は useMemo でサボらせる」という感覚を掴んでおきましょう。
今回のまとめ
- useMemo は「計算結果」を保存し、無駄な計算を防ぐ。
- useCallback は「関数」を保存し、子への無駄な伝播を防ぐ。
- どちらも 依存配列 で更新タイミングを決める。
- 何でもかんでもメモ化せず、パフォーマンスの問題が出てから使うのがプロのコツ。
次回予告:DOMを直接触りたい時は?
これまでは「Reactにお任せ」で画面を書き換えてきました。
しかし、特定の入力欄に「自動でフォーカスを当てる」とか「スクロール位置を操作する」など、Reactの枠を超えて直接HTML(DOM)を触りたい瞬間があります。
次回、「第13回:useRefの使い方:DOM要素への直接アクセスと値を保持するテクニック」。
Reactのルールを守りつつ、裏口からこっそり操作する「忍者のようなフック」を伝授します。お楽しみに!
本日の宿題:
サンプルコードの useMemo を外して、ただの関数として実行するように書き換えてみてください。入力欄(text)に文字を打つとき、動作が重くなるのを感じられますか?(※PCの性能によっては一瞬で終わるかもしれませんが、コンソールのログを見て実行回数を確認してみましょう!)


コメント