📝 はじめに
前回の記事では、useMemo を使って「値の再計算を防ぐ」方法を学びました。
今回はその兄弟的存在である useCallback に焦点を当てます。
useCallback は、 「関数をメモ化するフック」 です。
「値」と「関数」をそれぞれ最適化する useMemo と useCallback をセットで理解すると、Reactのパフォーマンス最適化の基礎がしっかり身につきます✨
⚙️ 前提条件
-
React Hooks(useState, useEffect, useMemo)の基本を理解している
-
コンポーネントの再レンダーの仕組みをなんとなく把握している
🎯 今回の目標
-
useCallback の基本的な使い方を理解する
-
useMemo との違いを明確にする
-
実際のコードでどんなときに効果があるか確認する
💡 useCallbackとは?
useCallback は 「同じ関数を毎回作り直さないようにする」 フックです。
Reactでは、コンポーネントが再レンダーされるたびに、関数も新しいインスタンスとして再生成 されます。
これが原因で、子コンポーネントが不要に再レンダーされる「useEffect」が無駄に発火するといった問題が発生することがあります。
🔹 基本構文
const memoizedCallback = useCallback(() => {
doSomething(value1);
}, [value2]);
第一引数:メモ化したい関数
第二引数:依存配列(この値が変わったときだけ新しい関数を生成)
✅ useMemo が「 値 を覚える」なら、
🧠 useCallback は「 関数 を覚える」!
🧩 サンプルコード:子コンポーネントの無駄な再レンダーを防ぐ
🧩 App.jsx(全体を動かすメインコンポーネント)
import React from "react";
import Parent from "./Parent";
const App = () => {
return (
<div style={{ padding: "30px", fontFamily: "sans-serif" }}>
<h1>useCallbackデモアプリ</h1>
<p>
親コンポーネントのカウントや入力に応じて、子コンポーネントのレンダー状況を確認してみましょう。
</p>
<Parent />
</div>
);
};
export default App;
✨ Parent.jsx
import React, { useState, useCallback } from "react";
import Child from "./Child";
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
// ❌ useCallbackなし → 毎回新しい関数として再生成される
// ✅ useCallbackあり → 同じ関数インスタンスを再利用
const handleClick = useCallback(() => {
console.log("ボタンがクリックされました!");
}, []);
return (
<div style={{ padding: "20px" }}>
<h2>useCallbackサンプル</h2>
<p>カウント: {count}</p>
<button onClick={() => setCount((prev) => prev + 1)}>+1</button>
<div style={{ marginTop: "20px" }}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="テキストを入力"
/>
</div>
{/* 👇 子コンポーネントへ関数を渡す */}
<Child onClick={handleClick} />
</div>
);
};
export default Parent;
🧩 Child.jsx
import React from "react";
const Child = React.memo(({ onClick }) => {
console.log("子コンポーネントがレンダーされました");
return (
<div style={{ marginTop: "20px" }}>
<button onClick={onClick}>子ボタンをクリック</button>
</div>
);
});
export default Child;
🧠 解説
React.memo() により、「props」が変わらない限り再レンダーしないようにしています。
しかし、useCallback を使わないと、onClick が毎回新しい関数になるため、
子コンポーネントが毎回再レンダーされてしまうのです。
useCallback を使うことで、関数の参照が変わらないため、無駄な再レンダーを防止できます💪
ちなみにReact.memoとは
こちらの記事をご覧ください
🔍 useMemoとの違いまとめ
| フック名 | メモ化対象 | 戻り値 | 主な用途 |
|---|---|---|---|
| useMemo | 値(計算結果) | 値 | 重い計算結果のキャッシュ |
| useCallback | 関数 | 関数 | 関数を子コンポーネントへ渡す際の再生成防止 |
💬 簡単に覚えるなら:
「値を覚える」 → useMemo
「関数を覚える」 → useCallback
⚠️ 注意点
-
むやみに使うと逆に複雑化する
→ メモリ消費や依存配列の管理コストが増えるため -
最適化の必要がある場面でのみ使う
→ 再レンダーや再計算に実害があるときだけ導入
🧭 まとめ
-
useCallback は「関数の再生成を防ぐ」ためのフック
-
React.memo と組み合わせると、子コンポーネントの無駄な再レンダーを防止できる
-
useMemo は値のメモ化、useCallback は関数のメモ化
「値を覚える」「関数を覚える」 と整理すれば理解しやすい
🏁 最後に
useCallback は、Reactの最適化を実践的に理解するための大切なステップです。
useMemo と組み合わせて使うことで、アプリ全体のパフォーマンスが向上します。
この段階まで理解できたあなたは、もう「初心者」卒業です。🚀
最後までご覧いただきありがとうございます。今後も引き続きお付き合いいただけると嬉しいです。