0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

⚡ ReactのuseCallback入門|関数の再生成を防いでパフォーマンスを最適化

Posted at

📝 はじめに

前回の記事では、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(全体を動かすメインコンポーネント)

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

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

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 と組み合わせて使うことで、アプリ全体のパフォーマンスが向上します。
この段階まで理解できたあなたは、もう「初心者」卒業です。🚀

最後までご覧いただきありがとうございます。今後も引き続きお付き合いいただけると嬉しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?