目次
1.useCallbackとは?
2.useCallbackの基本的な使い方
3.useCallbackを使うメリット
4.useCallbackの実践例
5.useCallbackの注意点
6.useCallbackとuseMemoの違い
7.useCallbackとReact.memoの違い
8.まとめ
useCallbackとは?
useCallback
は、Reactでメモ化したコールバック関数を作成するためのフック です。
通常、React ではコンポーネントが再レンダリングされるたびに関数が再生成されるという仕様があります。これは問題になることは少ないですが、以下のような場合に不要なレンダリングや処理の無駄を防ぐためにuseCallback
が役立ちます。
useCallback が必要なケース
- 関数をメモ化して、無駄な再生成を防ぐ
- 子コンポーネントに渡す関数が再生成されることを防ぎ、不要な再レンダリングを抑える
- パフォーマンスを最適化するための最適化(React.memo と組み合わせる)
useCallback の基本的な使い方
インポート方法
useCallback
はReactのフックなので、reactからインポートします。
import React, { useCallback } from 'react';
基本構文
const memoizedFunction = useCallBack(() => {
// 関数の処理
}, [依存する値]);
解説
-
useCallback
は第1引数に関数を取り、第2引数に依存配列を指定します。 - 依存配列の値が変わらない限り、関数は再生成されません。
シンプルな例
通常の関数では、コンポーネントが再レンダリングされるたびに関数が新しく作成されます。
function Example() {
const handleClick = () => {
console.log("ボタンがクリックされました");
};
return <button onClick={handleClick}>クリック</button>;
}
しかし、useCallback を使うと 関数のメモ化(再利用) が可能になります。
import React, { useCallback } from "react";
function Example() {
const handleClick = useCallback(() => {
console.log("ボタンがクリックされました");
}, []);
return <button onClick={handleClick}>クリック</button>;
}
解説
- handleClickは最初のレンダリング時に一度だけ作成され、それ以降は再利用される。
- 依存配列 [] を空にすると、コンポーネントが再レンダリングされても関数は再生成されない。
useCallbackを使うメリット
1.子コンポーネントの不要な再レンダリングを防ぐ
- useCallback を使わない場合、親コンポーネントが再レンダリングされると、子コンポーネントに渡す関数も毎回新しく作られてしまい、子コンポーネントが無駄に再レンダリングされる 可能性があります。
2. パフォーマンスの最適化
- 再生成を避けることで、処理のオーバーヘッドを削減 できる。
- 特にReact.memoと組み合わせると、最適化の効果が高まる。
useCallbackの実践例
子コンポーネントの再レンダリングを抑える
useCallback
を使わないと、親コンポーネントが再レンダリングされるたびに子コンポーネントに渡す関数が新しくなり、子コンポーネントが不要に再レンダリングされてしまいます。
import React, { useState } from 'react';
function child({ handleClick }) {
console.log("Child コンポーネントがレンダリングされました。");
return <button onClick={handleClick}>クリック</button>;
}
function Parent() {
const [count, setCount] = useState(0);
// 毎回新しい関数が作られる
const handleClick = () => {
console.log("ボタンがクリックされました。");
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count +1)}>カウントアップ</button>
<Child handelClick={handleClick} />
</div>
);
}
export default Parent;
解説
-
Parent
が再レンダリングされるたびにhandleClick
が再生成され、Child
が不要にレンダリングされる。
解決策(useCallback
を使用)
import React, { useState, useCallback } from "react";
function Child({ handleClick }) {
console.log("Child コンポーネントがレンダリングされました");
return <button onClick={handleClick}>クリック</button>;
}
const MemoizedChild = React.memo(Child);
function Parent() {
const [count, setCount] = useState(0);
// useCallback を使用して関数をメモ化
const handleClick = useCallback(() => {
console.log("ボタンがクリックされました");
}, []);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントアップ</button>
<MemoizedChild handleClick={handleClick} />
</div>
);
}
export default Parent;
解説
-
handleClick
がメモ化され、Parent
が再レンダリングされてもChild
が無駄に再レンダリングされない! -
React.memo
を使うことでChild
の再レンダリングを防止。
useCallback の注意点
1.むやみに使うと逆効果
- 使いすぎるとメモリを消費するため、最適化どころかパフォーマンスが悪化する可能性がある。
- 必要な場面だけに適用する(子コンポーネントの React.memo との組み合わせが有効)。
2.依存配列を適切に設定する
- 依存配列が適切でないと、古い状態を参照してしまい、意図しない動作をすることがある。
useCallback
とuseMemo
の違い
useCallback |
useMemo |
|
---|---|---|
目的 | 関数をメモ化する | 計算結果をメモ化する |
戻り値 | メモ化された関数 | メモ化された値 |
使いどころ | コールバック関数の再生成を防ぐ | 計算コストの高い値をキャッシュする |
例 | const memoizedFn = useCallback(() => {}, [deps]); |
const memoizedValue = useMemo(() => computeValue(), [deps]); |
useCallback
とReact.memo
の違い
useCallback |
React.memo |
|
---|---|---|
目的 | 関数をメモ化する | コンポーネントをメモ化する |
戻り値 | メモ化された関数 | メモ化されたコンポーネント |
使いどころ | コールバック関数の再生成を防ぐ | コンポーネントの再レンダリングを抑え、不要な描画を防ぐ |
例 | const memoizedFn = useCallback(() => {}, [deps]); |
const MemoizedComponent = React.memo(Component); |
まとめ
-
useCallback
は関数をメモ化し、再レンダリング時の無駄な関数再生成を防ぐ。 - 子コンポーネントの再レンダリングを抑える のに役立つ。
-
React.memo
と組み合わせると効果的。 - 適切な場面で使わないと逆効果になることもある。
-
useMemo
は値のメモ化、useCallback
は関数のメモ化をする点が違う。