<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useCallback</id>
	<title>Reactの基礎 - useCallback - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useCallback"/>
	<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useCallback&amp;action=history"/>
	<updated>2026-07-01T10:17:29Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useCallback&amp;diff=14548&amp;oldid=prev</id>
		<title>Wiki: ページの作成:「== 概要 == &lt;code&gt;useCallback&lt;/code&gt; は、関数をメモ化 (キャッシュ) するためのReact Hookである。&lt;br&gt; コンポーネントが再レンダリングされるたびに、コンポーネント内で定義された関数は新しい参照として再生成される。&lt;br&gt; &lt;br&gt; &lt;code&gt;useCallback&lt;/code&gt; を使用すると、依存配列の値が変化しない限り、同じ関数参照を返し続けることができる。&lt;br&gt; &lt;br&gt; 基本構文は &lt;…」</title>
		<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useCallback&amp;diff=14548&amp;oldid=prev"/>
		<updated>2026-03-07T22:04:38Z</updated>

		<summary type="html">&lt;p&gt;ページの作成:「== 概要 == &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; は、関数をメモ化 (キャッシュ) するためのReact Hookである。&amp;lt;br&amp;gt; コンポーネントが再レンダリングされるたびに、コンポーネント内で定義された関数は新しい参照として再生成される。&amp;lt;br&amp;gt; &amp;lt;br&amp;gt; &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; を使用すると、依存配列の値が変化しない限り、同じ関数参照を返し続けることができる。&amp;lt;br&amp;gt; &amp;lt;br&amp;gt; 基本構文は &amp;lt;…」&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 概要 ==&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; は、関数をメモ化 (キャッシュ) するためのReact Hookである。&amp;lt;br&amp;gt;&lt;br /&gt;
コンポーネントが再レンダリングされるたびに、コンポーネント内で定義された関数は新しい参照として再生成される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; を使用すると、依存配列の値が変化しない限り、同じ関数参照を返し続けることができる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
基本構文は &amp;lt;code&amp;gt;useCallback(fn, dependencies)&amp;lt;/code&amp;gt; であり、第1引数にメモ化したい関数、第2引数に依存配列を渡す。&amp;lt;br&amp;gt;&lt;br /&gt;
依存配列に含まれる値が変化した場合にのみ、新しい関数が作成されて返される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
ただし、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; 単体では再レンダリングの最適化は実現しない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされた子コンポーネントにpropsとして関数を渡す場合に組み合わせることにより、初めて最適化の効果が生まれる。&amp;lt;br&amp;gt;&lt;br /&gt;
子コンポーネントが &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされていない場合、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; を使用しても再レンダリングの防止には寄与しない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
また、2025年10月にリリースされたReact Compiler v1.0は、ビルド時に自動的にメモ化を適用する機能を持つ。&amp;lt;br&amp;gt;&lt;br /&gt;
React Compilerを導入した場合、単純な再レンダリング防止を目的とした &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の多くは不要になる。&amp;lt;br&amp;gt;&lt;br /&gt;
一方で、&amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の依存配列に関数を含める場合や、カスタムHookが関数を返す場合には、引き続き &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; が有効である。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 基本構文 ==&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の基本的な構文を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 const cachedFn = useCallback(fn, dependencies);&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、パラメータの詳細を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ useCallbackのパラメータ&lt;br /&gt;
! パラメータ !! 説明&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fn&amp;lt;/code&amp;gt; || メモ化したい関数&amp;lt;br&amp;gt;任意の引数を受け取り、任意の値を返すことができる。&amp;lt;br&amp;gt;初回レンダリング時にこの関数が返される。&amp;lt;br&amp;gt;次のレンダリング以降は、依存配列の値が前回と変わっていなければ同じ関数参照が返される。&amp;lt;br&amp;gt;依存配列の値が変化した場合は、新しい関数が作成されて返される。&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;fn&amp;lt;/code&amp;gt; の内部で参照する全てのリアクティブ値のリスト&amp;lt;br&amp;gt;props、state、コンポーネント内で宣言された変数・関数が対象となる。&amp;lt;br&amp;gt;各値は &amp;lt;code&amp;gt;Object.is()&amp;lt;/code&amp;gt; による厳密な比較で評価される。&amp;lt;br&amp;gt;値型は値そのもの、参照型はオブジェクトの参照が比較される。&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;依存配列を省略すると、毎回新しい関数が作成される。(メモ化されない)&amp;lt;br&amp;gt;空配列 &amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt; を指定すると、マウント時のみ関数が作成され、以降は同じ関数参照が返される。&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
TypeScriptでの主な型付けパターンを以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 // パターン1 : 型推論に任せる基本的な形式&lt;br /&gt;
 const handleSubmit = useCallback((event: React.FormEvent&amp;lt;HTMLFormElement&amp;gt;) =&amp;gt; {&lt;br /&gt;
    event.preventDefault();&lt;br /&gt;
 }, []);&lt;br /&gt;
 &lt;br /&gt;
 // パターン2 : React組み込みのイベントハンドラ型を使用する形式&lt;br /&gt;
 const handleChange = useCallback&amp;lt;React.ChangeEventHandler&amp;lt;HTMLInputElement&amp;gt;&amp;gt;((event) =&amp;gt; {&lt;br /&gt;
    console.log(event.target.value);&lt;br /&gt;
 }, []);&lt;br /&gt;
 &lt;br /&gt;
 // パターン3 : 型エイリアスを定義して使用する形式&lt;br /&gt;
 type ClickHandler = (id: string) =&amp;gt; void;&lt;br /&gt;
 const handleClick = useCallback&amp;lt;ClickHandler&amp;gt;((id) =&amp;gt; {&lt;br /&gt;
    console.log(id);&lt;br /&gt;
 }, []);&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== サンプルコード ==&lt;br /&gt;
==== 子コンポーネントへの関数渡し ====&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の最も基本的な使用パターンは、&amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされた子コンポーネントにコールバック関数をpropsとして渡す場合である。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
親コンポーネントが再レンダリングされると、コンポーネント内で定義された関数は毎回新しい参照として生成される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; は参照の同一性でpropsを比較するため、関数の参照が変わるたびに子コンポーネントが不必要に再レンダリングされる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; で関数参照を安定させることで、この不必要な再レンダリングを防止できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 // Reactのhooksとmemoをインポート&lt;br /&gt;
 // memo: コンポーネントのメモ化, useCallback: 関数のメモ化, useState: 状態管理&lt;br /&gt;
 import { memo, useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // ShippingFormコンポーネントのprops型定義&lt;br /&gt;
 interface ShippingFormProps {&lt;br /&gt;
    // 注文送信時のコールバック関数&lt;br /&gt;
    onSubmit: (orderDetails: { items: string[] }) =&amp;gt; void;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // React.memoでラップされた子コンポーネント&lt;br /&gt;
 // propsが変化しない限り再レンダリングされない&lt;br /&gt;
 const ShippingForm = memo(function ShippingForm({ onSubmit }: ShippingFormProps) {&lt;br /&gt;
    // フォーム送信ハンドラ&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;form onSubmit={(event) =&amp;gt; {&lt;br /&gt;
          event.preventDefault();          // デフォルトのフォーム送信をキャンセル&lt;br /&gt;
          onSubmit({ items: [&amp;#039;item1&amp;#039;] });  // 親から渡されたコールバックを実行&lt;br /&gt;
       }}&amp;gt;&lt;br /&gt;
          &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;注文を確定する&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/form&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // ProductPageコンポーネントのprops型定義&lt;br /&gt;
 interface ProductPageProps {&lt;br /&gt;
    productId: string;  // 商品ID&lt;br /&gt;
    referrer: string;   // 参照元情報&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 商品ページコンポーネント (親)&lt;br /&gt;
 export function ProductPage({ productId, referrer }: ProductPageProps) {&lt;br /&gt;
    // カウンタの状態管理 (ShippingFormとは無関係)&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
 &lt;br /&gt;
    // productIdまたはreferrerが変化した時のみ新しい関数を作成する&lt;br /&gt;
    // useCallbackにより、関数参照が安定化されShippingFormの不要な再レンダリングを防止&lt;br /&gt;
    const handleSubmit = useCallback((orderDetails: { items: string[] }) =&amp;gt; {&lt;br /&gt;
       console.log(&amp;#039;注文を送信しました:&amp;#039;, orderDetails, { productId, referrer });&lt;br /&gt;
    // 依存配列 : productIdまたはreferrerが変化した場合のみ関数を再生成&lt;br /&gt;
    }, [productId, referrer]);&lt;br /&gt;
 &lt;br /&gt;
    // 画面描画&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;&amp;gt;&lt;br /&gt;
          {/* countが変化しても、ShippingFormは再レンダリングされない */}&lt;br /&gt;
          {/* handleSubmitの参照が変わらないため、memoが効く */}&lt;br /&gt;
          &amp;lt;ShippingForm onSubmit={handleSubmit} /&amp;gt;&lt;br /&gt;
          {/* カウンタボタン (クリックしてもShippingFormは再レンダリングされない) */}&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; setCount(c =&amp;gt; c + 1)}&amp;gt;カウント: {count}&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== イベントハンドラの型付け ====&lt;br /&gt;
Reactが提供する組み込みのイベントハンドラ型を使用すると、イベントオブジェクトの型引数を省略して簡潔に記述できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
  // Reactのhooksとmemoをインポート&lt;br /&gt;
 import { memo, useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // SearchInputコンポーネントのprops型定義&lt;br /&gt;
 interface SearchInputProps {&lt;br /&gt;
    // React組み込みのイベントハンドラ型を使用 (型引数にHTMLInputElementを指定)&lt;br /&gt;
    onChange: React.ChangeEventHandler&amp;lt;HTMLInputElement&amp;gt;;     // 値変更イベントハンドラ&lt;br /&gt;
    onKeyDown: React.KeyboardEventHandler&amp;lt;HTMLInputElement&amp;gt;;  // キー押下イベントハンドラ&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // React.memoでラップされた検索入力コンポーネント&lt;br /&gt;
 // propsが変化しない限り再レンダリングされない&lt;br /&gt;
 const SearchInput = memo(function SearchInput({ onChange, onKeyDown }: SearchInputProps) {&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;input&lt;br /&gt;
          type=&amp;quot;text&amp;quot;&lt;br /&gt;
          onChange={onChange}    // 値変更時に呼び出される&lt;br /&gt;
          onKeyDown={onKeyDown}  // キー押下時に呼び出される&lt;br /&gt;
          placeholder=&amp;quot;検索キーワードを入力してください&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // 検索バーコンポーネント (親)&lt;br /&gt;
 export function SearchBar() {&lt;br /&gt;
    // 検索クエリの状態管理&lt;br /&gt;
    const [query, setQuery] = useState(&amp;#039;&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
    // React.ChangeEventHandler&amp;lt;HTMLInputElement&amp;gt; 型を明示する&lt;br /&gt;
    // 入力値変更時のハンドラ (useCallbackでメモ化)&lt;br /&gt;
    const handleChange = useCallback&amp;lt;React.ChangeEventHandler&amp;lt;HTMLInputElement&amp;gt;&amp;gt;(&lt;br /&gt;
       (event) =&amp;gt; {&lt;br /&gt;
          // 入力値をstateに反映&lt;br /&gt;
          setQuery(event.target.value);&lt;br /&gt;
       },&lt;br /&gt;
       // 依存配列が空のため、コンポーネントのライフサイクル中は同じ関数参照が維持される&lt;br /&gt;
       []&lt;br /&gt;
    );&lt;br /&gt;
 &lt;br /&gt;
    // React.KeyboardEventHandler&amp;lt;HTMLInputElement&amp;gt; 型を明示する&lt;br /&gt;
    // キー押下時のハンドラ (useCallbackでメモ化)&lt;br /&gt;
    const handleKeyDown = useCallback&amp;lt;React.KeyboardEventHandler&amp;lt;HTMLInputElement&amp;gt;&amp;gt;(&lt;br /&gt;
       (event) =&amp;gt; {&lt;br /&gt;
          // Enterキーが押された場合に検索を実行&lt;br /&gt;
          if (event.key === &amp;#039;Enter&amp;#039;) {&lt;br /&gt;
             console.log(&amp;#039;検索クエリ:&amp;#039;, query);&lt;br /&gt;
          }&lt;br /&gt;
       },&lt;br /&gt;
       // queryが変化すると関数を再生成 (最新のquery値をクロージャにキャプチャするため)&lt;br /&gt;
       [query]&lt;br /&gt;
    );&lt;br /&gt;
 &lt;br /&gt;
    // メモ化されたイベントハンドラをpropsとして渡す&lt;br /&gt;
    return &amp;lt;SearchInput onChange={handleChange} onKeyDown={handleKeyDown} /&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== カスタムHook内での使用 ====&lt;br /&gt;
カスタムHookが関数を返す場合、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; でラップすることが推奨される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
カスタムHookを使用するコンポーネントが、返された関数を &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の依存配列に含めたり、&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされた子コンポーネントに渡したりする可能性があるためである。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 // Reactのhooksをインポート&lt;br /&gt;
 // useCallback: 関数のメモ化, useState: 状態管理&lt;br /&gt;
 import { useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // 選択時のコールバック関数の型定義&lt;br /&gt;
 type OnSelect = (id: string) =&amp;gt; void;&lt;br /&gt;
 &lt;br /&gt;
 // カスタムHookの戻り値の型定義&lt;br /&gt;
 interface SelectionState {&lt;br /&gt;
    selectedId: string | null;   // 選択中のID (nullの場合は未選択)&lt;br /&gt;
    handleSelect: OnSelect;      // 選択ハンドラ関数&lt;br /&gt;
    handleClear: () =&amp;gt; void;     // 選択解除ハンドラ関数&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 選択状態を管理するカスタムHook&lt;br /&gt;
 // useCallbackで関数をメモ化し、使用するコンポーネントでの最適化を可能にする&lt;br /&gt;
 function useSelection(): SelectionState {&lt;br /&gt;
    // 選択中のIDを管理するstate&lt;br /&gt;
    const [selectedId, setSelectedId] = useState&amp;lt;string | null&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    // useCallbackでラップして、参照を安定させる&lt;br /&gt;
    // 依存配列が空のため、コンポーネントのライフサイクル中は同じ関数参照が維持される&lt;br /&gt;
    const handleSelect = useCallback&amp;lt;OnSelect&amp;gt;((id) =&amp;gt; {&lt;br /&gt;
       setSelectedId(id);&lt;br /&gt;
    }, []);&lt;br /&gt;
 &lt;br /&gt;
    // 選択解除ハンドラ (useCallbackでメモ化)&lt;br /&gt;
    // 依存配列が空のため、コンポーネントのライフサイクル中は同じ関数参照が維持される&lt;br /&gt;
    const handleClear = useCallback(() =&amp;gt; {&lt;br /&gt;
       setSelectedId(null);&lt;br /&gt;
    }, []);&lt;br /&gt;
 &lt;br /&gt;
    // 選択状態とハンドラ関数をオブジェクトとして返す&lt;br /&gt;
    return { selectedId, handleSelect, handleClear };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // カスタムHookを使用するコンポーネント&lt;br /&gt;
 export function ItemList() {&lt;br /&gt;
    // カスタムHookから選択状態とハンドラを取得&lt;br /&gt;
    const { selectedId, handleSelect, handleClear } = useSelection();&lt;br /&gt;
 &lt;br /&gt;
    // 画面描画&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          {/* 現在の選択状態を表示 (nullの場合は「なし」と表示) */}&lt;br /&gt;
          &amp;lt;p&amp;gt;選択中: {selectedId ?? &amp;#039;なし&amp;#039;}&amp;lt;/p&amp;gt;&lt;br /&gt;
          {/* Item 1選択ボタン (クリックでhandleSelectを呼び出し) */}&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; handleSelect(&amp;#039;item-1&amp;#039;)}&amp;gt;Item 1を選択&amp;lt;/button&amp;gt;&lt;br /&gt;
          {/* Item 2選択ボタン (クリックでhandleSelectを呼び出し) */}&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; handleSelect(&amp;#039;item-2&amp;#039;)}&amp;gt;Item 2を選択&amp;lt;/button&amp;gt;&lt;br /&gt;
          {/* 選択解除ボタン (クリックでhandleClearを呼び出し) */}&lt;br /&gt;
          &amp;lt;button onClick={handleClear}&amp;gt;選択を解除&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== useEffectとの組み合わせ ====&lt;br /&gt;
関数を &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の依存配列に含める必要がある場合、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; でメモ化することで無限ループを防止できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
ただし、関数がコンポーネント外のデータに依存しない場合は、関数を直接 &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の内部に移動する方がより適切である。&amp;lt;br&amp;gt;&lt;br /&gt;
その場合、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; は不要になり、依存配列の管理も簡素化される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 // Reactのhooksをインポート&lt;br /&gt;
 // useCallback: 関数のメモ化, useEffect: 副作用の管理, useState: 状態管理&lt;br /&gt;
 import { useCallback, useEffect, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // ユーザデータのインターフェース定義&lt;br /&gt;
 interface UserData {&lt;br /&gt;
    id: string;      // ユーザID&lt;br /&gt;
    name: string;    // ユーザ名&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // UserProfileコンポーネントのprops型定義&lt;br /&gt;
 interface UserProfileProps {&lt;br /&gt;
    userId: string;  // 取得対象のユーザID&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // パターン1 : useCallbackで関数をメモ化してuseEffectの依存配列に含める&lt;br /&gt;
 export function UserProfileWithCallback({ userId }: UserProfileProps) {&lt;br /&gt;
    const [user, setUser] = useState&amp;lt;UserData | null&amp;gt;(null);  // ユーザデータのstate (取得前はnull)&lt;br /&gt;
 &lt;br /&gt;
    // ユーザデータを取得する関数 (useCallbackでメモ化)&lt;br /&gt;
    // userIdが変化した場合のみ関数が再生成される&lt;br /&gt;
    const fetchUser = useCallback(async () =&amp;gt; {&lt;br /&gt;
       const response = await fetch(`/api/users/${userId}`);  // APIからユーザデータを取得&lt;br /&gt;
       const data = await response.json() as UserData;        // レスポンスをJSONとしてパース (UserData型にキャスト)&lt;br /&gt;
       setUser(data);                                         // stateを更新&lt;br /&gt;
    // 依存配列: userIdが変化した場合のみ関数を再生成&lt;br /&gt;
    }, [userId]);&lt;br /&gt;
 &lt;br /&gt;
    // コンポーネントマウント時またはfetchUserが変化した時に実行&lt;br /&gt;
    useEffect(() =&amp;gt; {&lt;br /&gt;
       fetchUser();&lt;br /&gt;
    // fetchUserをuseCallbackでメモ化しているため、userIdが変化した時のみ再実行される&lt;br /&gt;
    }, [fetchUser]);&lt;br /&gt;
 &lt;br /&gt;
    // ユーザ名を表示 (取得前は「読み込み中...」を表示)&lt;br /&gt;
    return &amp;lt;div&amp;gt;{user?.name ?? &amp;#039;読み込み中...&amp;#039;}&amp;lt;/div&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // パターン2 (推奨) : 関数をuseEffect内に移動してuseCallbackを不要にする&lt;br /&gt;
 export function UserProfileWithInlineFunction({ userId }: UserProfileProps) {&lt;br /&gt;
    const [user, setUser] = useState&amp;lt;UserData | null&amp;gt;(null);     // ユーザデータのstate (取得前はnull)&lt;br /&gt;
 &lt;br /&gt;
    // コンポーネントマウント時またはuserIdが変化した時に実行&lt;br /&gt;
    useEffect(() =&amp;gt; {&lt;br /&gt;
       // useEffect内に直接定義することで、useCallbackが不要になる&lt;br /&gt;
       async function fetchUser() {&lt;br /&gt;
          const response = await fetch(`/api/users/${userId}`);  // APIからユーザデータを取得&lt;br /&gt;
          const data = await response.json() as UserData;        // レスポンスをJSONとしてパース (UserData型にキャスト)&lt;br /&gt;
          setUser(data);                                         // stateを更新&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       // 定義した関数を実行&lt;br /&gt;
       fetchUser();&lt;br /&gt;
    // userIdのみを依存配列に指定する (関数を外部で定義する必要がない)&lt;br /&gt;
    }, [userId]);&lt;br /&gt;
 &lt;br /&gt;
    // ユーザ名を表示 (取得前は「読み込み中...」を表示)&lt;br /&gt;
    return &amp;lt;div&amp;gt;{user?.name ?? &amp;#039;読み込み中...&amp;#039;}&amp;lt;/div&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== React.memoとuseCallbackの組み合わせ ====&lt;br /&gt;
最適化パターンとして、Todoリストを例に &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; と &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の組み合わせを示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
state更新関数 (アップデータ関数) を使用すると、現在のstateの値を依存配列に含めることなく更新できるため、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の依存配列を最小限に抑えられる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 // Reactのhooksとmemoをインポート&lt;br /&gt;
 // memo: コンポーネントのメモ化, useCallback: 関数のメモ化, useState: 状態管理&lt;br /&gt;
 import { memo, useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // Todoアイテムのインターフェース定義&lt;br /&gt;
 interface Todo {&lt;br /&gt;
    id: string;    // Todoの一意識別子&lt;br /&gt;
    text: string;  // Todoのテキスト内容&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // TodoItemコンポーネントのprops型定義&lt;br /&gt;
 interface TodoItemProps {&lt;br /&gt;
    id: string;                                    // Todo ID&lt;br /&gt;
    text: string;                                  // Todo テキスト&lt;br /&gt;
    onDelete: (id: string) =&amp;gt; void;                // 削除ハンドラ&lt;br /&gt;
    onUpdate: (id: string, text: string) =&amp;gt; void;  // 更新ハンドラ&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // React.memoでラップして、propsが変化しない限り再レンダリングを防止する&lt;br /&gt;
 // 関数参照がuseCallbackで安定している場合、不要な再レンダリングを回避できる&lt;br /&gt;
 const TodoItem = memo(function TodoItem({ id, text, onDelete, onUpdate }: TodoItemProps) {&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;li&amp;gt;&lt;br /&gt;
          {/* テキスト入力フィールド (値が変更されるとonUpdateを呼び出し) */}&lt;br /&gt;
          &amp;lt;input&lt;br /&gt;
             value={text}&lt;br /&gt;
             onChange={(e) =&amp;gt; onUpdate(id, e.target.value)}&lt;br /&gt;
          /&amp;gt;&lt;br /&gt;
          {/* 削除ボタン (クリックでonDeleteを呼び出し) */}&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; onDelete(id)}&amp;gt;削除&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/li&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // Todoリストコンポーネント (親)&lt;br /&gt;
 export function TodoList() {&lt;br /&gt;
    const [todos, setTodos] = useState&amp;lt;Todo[]&amp;gt;([]);                           // Todoの配列を管理するstate&lt;br /&gt;
 &lt;br /&gt;
    // Todo追加ハンドラ (useCallbackでメモ化)&lt;br /&gt;
    // 依存配列が空のため、常に同じ関数参照が返される&lt;br /&gt;
    const handleAddTodo = useCallback(() =&amp;gt; {&lt;br /&gt;
       const newTodo: Todo = { id: crypto.randomUUID(), text: &amp;#039;新しいTodo&amp;#039; };  // 新しいTodoを作成 (crypto.randomUUID()で一意IDを生成)&lt;br /&gt;
       &lt;br /&gt;
       // アップデーター関数を使用してtodosへの依存をなくす&lt;br /&gt;
       // prevは現在のstate値を受け取るため、todosを依存配列に含める必要がない&lt;br /&gt;
       setTodos((prev) =&amp;gt; [...prev, newTodo]);&lt;br /&gt;
    }, []); // 依存配列が空のため、常に同じ関数参照が返される&lt;br /&gt;
 &lt;br /&gt;
    // Todo削除ハンドラ (useCallbackでメモ化)&lt;br /&gt;
    // アップデータ関数を使用することにより、todosを依存配列に含めずに済む&lt;br /&gt;
    const handleDelete = useCallback((id: string) =&amp;gt; {&lt;br /&gt;
       // アップデータ関数でtodosを参照する&lt;br /&gt;
       // 指定されたID以外のTodoでフィルタリング&lt;br /&gt;
       setTodos((prev) =&amp;gt; prev.filter((todo) =&amp;gt; todo.id !== id));&lt;br /&gt;
    }, []); // todosを依存配列に含めずに済む&lt;br /&gt;
 &lt;br /&gt;
    // Todo更新ハンドラ (useCallbackでメモ化)&lt;br /&gt;
    // アップデーター関数を使用することで、todosを依存配列に含めずに済む&lt;br /&gt;
    const handleUpdate = useCallback((id: string, text: string) =&amp;gt; {&lt;br /&gt;
       // 指定されたIDのTodoのテキストを更新&lt;br /&gt;
       // mapでTodo配列を走査し、IDが一致する要素のみ更新&lt;br /&gt;
       setTodos((prev) =&amp;gt; prev.map((todo) =&amp;gt; todo.id === id ? { ...todo, text } : todo));&lt;br /&gt;
    }, []); // todosを依存配列に含めずに済む&lt;br /&gt;
 &lt;br /&gt;
    // 画面描画&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;&amp;gt;&lt;br /&gt;
          {/* Todo追加ボタン */}&lt;br /&gt;
          &amp;lt;button onClick={handleAddTodo}&amp;gt;Todoを追加&amp;lt;/button&amp;gt;&lt;br /&gt;
          {/* Todoリスト */}&lt;br /&gt;
          &amp;lt;ul&amp;gt;&lt;br /&gt;
             {/* 各Todoアイテムを表示 */}&lt;br /&gt;
             {todos.map((todo) =&amp;gt; (&lt;br /&gt;
                &amp;lt;TodoItem&lt;br /&gt;
                   key={todo.id}           // Reactのリストレンダリング用キー&lt;br /&gt;
                   id={todo.id}            // Todo ID&lt;br /&gt;
                   text={todo.text}        // Todo テキスト&lt;br /&gt;
                   onDelete={handleDelete} // メモ化された削除ハンドラ&lt;br /&gt;
                   onUpdate={handleUpdate} // メモ化された更新ハンドラ&lt;br /&gt;
                /&amp;gt;&lt;br /&gt;
             ))}&lt;br /&gt;
          &amp;lt;/ul&amp;gt;&lt;br /&gt;
       &amp;lt;/&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== React Compilerとの関係 ==&lt;br /&gt;
==== React Compilerによる自動メモ化 ====&lt;br /&gt;
React Compiler (旧称: React Forget) は、2025年10月7日にv1.0としてリリースされた。&amp;lt;br&amp;gt;&lt;br /&gt;
React 17以上で動作し、React Nativeにも対応している。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
React Compilerはビルド時にReactコードを静的に解析して、必要な箇所に自動的にメモ化を適用する。&amp;lt;br&amp;gt;&lt;br /&gt;
これにより、開発者が手動で &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; や &amp;lt;code&amp;gt;useMemo&amp;lt;/code&amp;gt;、&amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; を記述しなくても、同等の最適化が自動で行われる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
さらに、条件付きメモ化等、手動では実装が困難な最適化もコンパイラが判断して適用するため、手動メモ化よりも精度の高い最適化が期待できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 手動メモ化が必要なケース ====&lt;br /&gt;
React Compilerを導入した後も、以下の場面では &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; が引き続き有効または必要となる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の依存配列に関数を含める場合&lt;br /&gt;
*: 無限ループを防止するために、関数の参照を安定させる必要がある場合&lt;br /&gt;
*: ただし、可能であれば関数を &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; 内に移動する方を優先する。&lt;br /&gt;
* カスタムHookが関数を返す場合&lt;br /&gt;
*: カスタムHookの利用者が返された関数をどのように使用するか予測できないため、参照の安定性を保証する目的で &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; を使用する。&lt;br /&gt;
* React Compilerが適用されない環境との互換性が必要な場合&lt;br /&gt;
*: React Compilerを導入していないプロジェクトや段階的に移行しているプロジェクトでは引き続き手動メモ化が必要となる。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== useCallbackが不要になるケース ====&lt;br /&gt;
React Compilerが導入された環境では、以下に示す用途の &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; はコンパイラによる自動最適化でカバーされる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 単純な再レンダリングを防止するだけの目的&lt;br /&gt;
*: 親コンポーネントの再レンダリング時に、子コンポーネントへの関数propsの参照を安定させるだけの用途&lt;br /&gt;
* &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; と組み合わせた参照安定性の確保&lt;br /&gt;
*: コンパイラが自動的に同等の最適化を適用するため、手動での記述が不要になる。&lt;br /&gt;
* 新規コードにおけるほとんどのケース&lt;br /&gt;
*: React Compiler導入済みの新規プロジェクトでは、コンパイラのデフォルト動作に任せることが推奨される。&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== useMemoとの違い ==&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; と &amp;lt;code&amp;gt;useMemo&amp;lt;/code&amp;gt; は関連するHookであり、以下の等価関係が成立する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useCallback, useMemo } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // useCallbackの使用&lt;br /&gt;
 const cachedFn = useCallback(() =&amp;gt; {&lt;br /&gt;
    doSomething(a, b);&lt;br /&gt;
 }, [a, b]);&lt;br /&gt;
 &lt;br /&gt;
 // 上記はuseMemoで以下のように記述することと同等である&lt;br /&gt;
 const cachedFnWithMemo = useMemo(() =&amp;gt; {&lt;br /&gt;
    return () =&amp;gt; {&lt;br /&gt;
       doSomething(a, b);&lt;br /&gt;
    };&lt;br /&gt;
 }, [a, b]);&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback(fn, deps)&amp;lt;/code&amp;gt; は、&amp;lt;code&amp;gt;useMemo(() =&amp;gt; fn, deps)&amp;lt;/code&amp;gt; と同等である。&amp;lt;br&amp;gt;&lt;br /&gt;
Reactは利便性のために &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; という専用のHookを提供している。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、両者の使い分けの基準を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ useCallbackとuseMemoの使い分け&lt;br /&gt;
! Hook !! メモ化の対象 !! 主な用途&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; || 関数そのもの || &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされた子コンポーネントに&amp;lt;br&amp;gt;propsとして渡す関数 / &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; の依存配列に含める関数&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;useMemo&amp;lt;/code&amp;gt; || 計算結果 (値) || 重い計算処理の結果 / フィルタリングや変換処理の結果 / 参照の安定性が必要なオブジェクトや配列&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 注意事項 ==&lt;br /&gt;
==== useCallbackだけでは最適化にならない ====&lt;br /&gt;
&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; 単体では、子コンポーネントの再レンダリングを防止できない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
子コンポーネントが &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされていない場合、親コンポーネントが再レンダリングされると関数の参照に関係なく子コンポーネントも再レンダリングされる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // React.memoでラップされていないコンポーネント&lt;br /&gt;
 function ChildComponent({ onClick }: { onClick: () =&amp;gt; void }) {&lt;br /&gt;
    console.log(&amp;#039;ChildComponentがレンダリングされた&amp;#039;);&lt;br /&gt;
    return &amp;lt;button onClick={onClick}&amp;gt;クリック&amp;lt;/button&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export function ParentComponent() {&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
 &lt;br /&gt;
    // useCallbackを使っているが、子コンポーネントがmemoでラップされていないため効果がない&lt;br /&gt;
    const handleClick = useCallback(() =&amp;gt; {&lt;br /&gt;
       console.log(&amp;#039;クリックされた&amp;#039;);&lt;br /&gt;
    }, []);&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;&amp;gt;&lt;br /&gt;
          {/* countが変化するたびに、ChildComponentも再レンダリングされてしまう */}&lt;br /&gt;
          &amp;lt;ChildComponent onClick={handleClick} /&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; setCount(c =&amp;gt; c + 1)}&amp;gt;カウント: {count}&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== クロージャの古い値を参照する問題 ====&lt;br /&gt;
依存配列に必要な値を含め忘れると、関数が古いクロージャの値を参照し続けるバグが発生する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useCallback, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export function CounterWithBug() {&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
 &lt;br /&gt;
    // 問題 : countが依存配列に含まれていないため、常に初期値の0を参照する&lt;br /&gt;
    const handleAlertBad = useCallback(() =&amp;gt; {&lt;br /&gt;
       alert(`現在のカウント: ${count}`); // 常に0が表示される&lt;br /&gt;
    }, []); // countが含まれていない&lt;br /&gt;
 &lt;br /&gt;
    // 解決策1 : countを依存配列に含める&lt;br /&gt;
    const handleAlertGood = useCallback(() =&amp;gt; {&lt;br /&gt;
       alert(`現在のカウント: ${count}`);&lt;br /&gt;
    }, [count]); // countが変化するたびに新しい関数が作成される&lt;br /&gt;
 &lt;br /&gt;
    // 解決策2 : state更新関数を使用して依存配列を回避する&lt;br /&gt;
    const handleIncrement = useCallback(() =&amp;gt; {&lt;br /&gt;
       setCount(c =&amp;gt; c + 1); // countへの依存なしにstateを更新できる&lt;br /&gt;
    }, []); // 依存配列が空で済む&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;カウント: {count}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleIncrement}&amp;gt;+1&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleAlertBad}&amp;gt;バグあり (カウントを表示)&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleAlertGood}&amp;gt;正しい (カウントを表示)&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 依存配列の不適切な指定 ====&lt;br /&gt;
依存配列にオブジェクトリテラルや配列リテラルを直接含めると、レンダリングのたびに新しい参照が生成されるため、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; のメモ化が機能しない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useCallback } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 interface Config {&lt;br /&gt;
    theme: string;&lt;br /&gt;
    size: number;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 interface ComponentProps {&lt;br /&gt;
    config: Config;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export function Component({ config }: ComponentProps) {&lt;br /&gt;
    // 問題 : configはレンダリングのたびに新しい参照になる可能性があるため、&lt;br /&gt;
    // useCallbackは毎回新しい関数を作成してしまう&lt;br /&gt;
    const handleActionBad = useCallback(() =&amp;gt; {&lt;br /&gt;
       console.log(config.theme, config.size);&lt;br /&gt;
    }, [config]); // configが参照型の場合、毎回新しい参照になりうる&lt;br /&gt;
 &lt;br /&gt;
    // 解決策 : オブジェクトのプリミティブ値を個別に依存配列に含める&lt;br /&gt;
    const handleActionGood = useCallback(() =&amp;gt; {&lt;br /&gt;
       console.log(config.theme, config.size);&lt;br /&gt;
    }, [config.theme, config.size]); // プリミティブ値で比較される&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;button onClick={handleActionGood}&amp;gt;実行&amp;lt;/button&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== useCallbackを使うべきでない場面 ====&lt;br /&gt;
以下に示す場面では、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; を使用しても効果がなく、ソースコードの複雑さが増すだけとなる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 関数をメモ化するだけで、子コンポーネントが &amp;lt;code&amp;gt;React.memo&amp;lt;/code&amp;gt; でラップされていない場合&lt;br /&gt;
*: メモ化した関数を受け取る子コンポーネントが最適化されていなければ、&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; の効果は得られない。&lt;br /&gt;
* 単純なイベントハンドラで、子コンポーネントの最適化が不要な場合&lt;br /&gt;
*: フォームのボタン等、最適化が不要なシンプルな用途では &amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; は不要である。&lt;br /&gt;
* 関数が軽量な処理しか行わない場合&lt;br /&gt;
*: メモ化のオーバーヘッドが最適化の効果を上回る可能性がある。&lt;br /&gt;
* React Compilerを導入済みのプロジェクトで、新規作成する再レンダリング防止目的のコード&lt;br /&gt;
*: コンパイラが自動的に最適化を適用するため、手動でのメモ化は不要である。&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 関連情報 ==&lt;br /&gt;
* [https://react.dev/reference/react/useCallback useCallback - React公式ドキュメント]&lt;br /&gt;
* [https://react.dev/reference/react/useMemo useMemo - React公式ドキュメント]&lt;br /&gt;
* [https://react.dev/learn/react-compiler React Compiler - React公式ドキュメント]&lt;br /&gt;
* [[Reactの基礎 - Hooksの基礎]]&lt;br /&gt;
* [[Reactの基礎 - useState]]&lt;br /&gt;
* [[Reactの基礎 - useEffect]]&lt;br /&gt;
* [[Reactの基礎 - useMemo]]&lt;br /&gt;
* [[Reactの基礎 - カスタムHook]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{#seo:&lt;br /&gt;
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki&lt;br /&gt;
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板,React,JavaScript,TypeScript,TSX,useCallback,useMemo,Hooks,メモ化,memoize,React.memo,カスタムHook,React Compiler,パフォーマンス最適化&lt;br /&gt;
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux&lt;br /&gt;
|image=/resources/assets/MochiuLogo_Single_Blue.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
__FORCETOC__&lt;br /&gt;
[[カテゴリ:Rust]][[カテゴリ:Web]]&lt;/div&gt;</summary>
		<author><name>Wiki</name></author>
	</entry>
</feed>