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】パフォーマンス最適化を行うためのフックuseMemoとuseCallbackについて

Posted at

usememouseCallbackについて

useMemo useCallback は、Reactでパフォーマンス最適化を行うためのフック(Hook)です。

前提:Reactの再レンダーの仕組み

Reactは、親コンポーネントが再レンダーすると子コンポーネントも再レンダーします。

そのとき、
■関数 (() => {...})
■オブジェクト ({})
などは毎回新しく作られる別のものと見なされます。

そのため、子コンポーネントが React.memo でラップされていても、
props に「新しい関数」や「新しいオブジェクト」が渡されると
無駄に再レンダーされてしまうことがあります。

useMemoとは?

⇒ 「計算結果をメモ(記憶)しておく」フック

sample.tsx
const memoizedValue = useMemo(() => {
  return heavyCalculation(a, b);
}, [a, b]);

■「a」 または「 b 」が変わったときだけ再計算。
■それ以外は前回の結果を再利用。

使う場面

■計算コストが高い処理を繰り返し呼びたくないとき
■オブジェクトや配列を安定させたいとき(useEffectReact.memoの依存関係を安定化)

サンプル(useMemo)

sample.tsx
import React, { useMemo, useState } from "react";

export const UseMemoExample = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  // 重い計算(実際は単純化してます)
  const heavyResult = useMemo(() => {
    console.log("重い計算を実行中…");
    return count * 2;
  }, [count]); // ← countが変わったときだけ計算される!

  return (
    <div>
      <h2>useMemoの例</h2>
      <p>結果: {heavyResult}</p>
      <button onClick={() => setCount((c) => c + 1)}>+1</button>
      <input
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="テキスト入力"
      />
    </div>
  );
};

useCallbackとは?

☞「関数をメモ(記憶)しておく」フック

sample.tsx
const memoizedFn = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

■「a 」や「 b 」が変わったときだけ新しい関数を作る。
■それ以外は同じ関数インスタンスを再利用

使う場面

■子コンポーネントにコールバック関数を渡すとき
React.memo で無駄な再レンダーを防ぐ)
■イベントハンドラ関数を安定させたいとき

sample.tsx
import React, { useState, useCallback, memo } from "react";

// 子コンポーネント
const ChildButton = memo(({ onClick }: { onClick: () => void }) => {
  console.log("👶 ChildButtonレンダー");
  return <button onClick={onClick}>子ボタンをクリック</button>;
});

export const UseCallbackExample = () => {
  const [count, setCount] = useState(0);

  // useCallbackを使わない場合 → 毎回新しい関数になる
  const handleClick = useCallback(() => {
    console.log("クリックされました");
  }, []); // 依存がないので常に同じ関数参照を維持

  return (
    <div>
      <h2>useCallbackの例</h2>
      <p>count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>+1</button>
      <ChildButton onClick={handleClick} />
    </div>
  );
};

👉 count を増やしても、子の ChildButton は再レンダーされません!
(useCallback がなければ、毎回新しい関数として再レンダーされてしまう)

 フック   メモする対象   よく使う場面   効果 
 useMemo   値(計算結果やオブジェクト)   重い計算、配列・オブジェクト生成   再計算を防ぐ 
 useCallback   関数   子コンポーネントに渡す関数   無駄な再レンダーを防ぐ 

⚠️ 注意点

なんでもかんでもuseMemo/useCallbackを使うのはNG!
■コードが読みにくくなる
■メモリを多く使う場合がある

実際に遅くなることもある(軽い処理なら不要)

👉 「レンダーごとに重い処理が走る」
 または
 「props経由で再レンダーが起きて困る」
というときだけ使いましょう。

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?