目次
開発環境
- Visual Studio Code:version 1.73.0
- OS:Windows10
- react:18.2.0
- react-dom:18.2.0
ReactのuseCallbackとは
useCallbackは、再レンダー間で関数定義をキャッシュできるようにするためのReact Hookです。
関数をキャッシュに保持することにより、関数の依存関係が変わらない限り、関数を再利用することで関数が不要に再作成されるのを防ぐことができます。
そのため、子コンポーネントに渡すコールバック関数が常に同じ参照を持つため、子コンポーネントの不要な再レンダリングを防ぎ、パフォーマンスを最適化することができます。
公式ドキュメント:https://ja.react.dev/reference/react/useCallback
useCallbackの基本構文
useCallbackの基本構文は以下の通りです。
1 2 3 | const memoizedCallback = useCallback(() => { // 実行される処理 }, [dependencies]); |
useCallbackの使い方
useCallbackの具体的な使い方を説明していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import './App.css'; import React, { useState, useCallback } from 'react'; import Child from './Child'; function App() { const [count, setCount] = useState(0); const [countWithCallback, setCountWithCallback] = useState(0); // useCallbackを使用しない関数 const increment = () => { setCount(prevCount => prevCount + 1); }; // useCallbackを使用する関数 const incrementWithCallback = useCallback(() => { setCountWithCallback(prevCount => prevCount + 1); }, []); return ( <div> <h1>React Hooks Tutorial</h1> <hr /> <h2>useCallback</h2> <p>Count: {count}</p> <button onClick={increment}>Increment Count</button> <Child onClick={increment} label="Increment without useCallback" /> <p>Count with useCallback: {countWithCallback}</p> <button onClick={incrementWithCallback}>Increment Count with useCallback</button> <Child onClick={incrementWithCallback} label="Increment with useCallback" /> </div> ); } export default App; |
1 2 3 4 5 6 7 8 9 10 11 12 13 | import React from 'react'; function Child({ onClick, label }) { console.log(`${label} rendered`); return ( <div> <button onClick={onClick}>{label}</button> </div> ); } export default React.memo(Child); |
Increment without useCallbackボタンをクリックをするとChildコンポーネントが再レンダリングされます。
毎回新しい関数が生成されるため、React.memoによる最適化が無効になり、コンソールにIncrement without useCallback renderedが表示されます。
Increment with useCallbackボタンをクリックするとChildコンポーネントは再レンダリングされません。
useCallbackによりメモ化された関数が使用されるため、関数の参照が変わらず、React.memoによる最適化が有効になり、コンソールにIncrement with useCallback renderedが表示されません。
これにより、useCallbackとReact.memoを組み合わせることで、不要な再レンダリングを防ぎ、パフォーマンスの最適化ができることを示しています。
useStateフックの使用
1 2 | const [count, setCount] = useState(0); const [countWithCallback, setCountWithCallback] = useState(0); |
countとcountWithCallbackという2つの状態変数を定義しています。
それぞれの状態を更新するためにsetCountとsetCountWithCallbackの関数が使われます。
increment関数
1 2 3 | const increment = () => { setCount(prevCount => prevCount + 1); }; |
useCallbackを使用しない通常の関数です。
setCountを使ってcountの値を1増やす処理ですが、 prevCount => prevCount + 1
という形で、現在の状態に依存して新しい状態を設定します。
incrementWithCallback関数
1 2 3 | const incrementWithCallback = useCallback(() => { setCountWithCallback(prevCount => prevCount + 1); }, []); |
useCallbackを使用して定義された関数です。
setCountWithCallbackを使ってcountWithCallbackの値を1増やします。
依存配列が空のため、この関数はコンポーネントの初回レンダリング時にのみ作成され、その後は再レンダリングされても同じ関数が使用されます。
Childコンポーネントの使用
1 2 | <Child onClick={increment} label="Increment without useCallback" /> <Child onClick={incrementWithCallback} label="Increment with useCallback" /> |
ChildコンポーネントにonClickとlabelのpropsを渡しています。
onClickにはそれぞれincrementとincrementWithCallbackの関数を渡しています。
React.memoの使用
1 2 3 4 5 6 7 8 9 | const Child = React.memo(({ onClick, label }) => { console.log(`${label} rendered`); return ( <div> <button onClick={onClick}>{label}</button> </div> ); }); |
React.memoは高階コンポーネントで、Childコンポーネントが受け取るpropsが変更されない限り再レンダリングされないようにします。
これにより、不要な再レンダリングを防ぎ、パフォーマンスを向上させます。
また、ChildコンポーネントはonClickとlabelという2つのpropsを受け取り、ボタンがクリックされるとonClick関数が実行されます。
おわりに
ReactのuseCallbackの使い方について説明してきましたが、いかがだったでしょうか。
useCallbackを使用することで、初回のレンダリング時に関数をキャッシュに保持し、不要なレンダリングを防ぐことでパフォーマンスの向上が期待できます。
特に、大規模なアプリケーションや再レンダリングコストが高いコンポーネントで効果を発揮します。
例えば、データの変更が頻繁に起こるダッシュボードやリアルタイム更新が必要なチャットアプリなどで、useCallbackを適切に使用することで、パフォーマンスが大幅に向上する可能性があります。
ぜひ、ReactフックのuseCallbackを使いこなして、効率的なReactアプリケーションを作成しましょう。