useCallback
フックの代わりにReactの useEffect
フックを使用する場合の使用例を理解しようとしています。
どちらも入力の状態変化のリスナーとして機能しているように見えます( React Docs からの例):
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
ただし、useEffect
フックを使用すると、以前にcomponentWillUnmount
を使用していた場合にリソースをクリーンアップできるという追加の利点があります。
それでは、useCallback
を使用する良いユースケースは何ですか?そして、私はここで何が欠けていますか?
useEffect
には、それに関連する非常に具体的なタイミングの側面があります ここ について読むことができます。指定された関数は、レンダリングが完了し、DOMが更新された後に実行されます。これは、2番目の引数の配列で指定された値のいずれかが変化するレンダリングごとに発生します。
useCallback
は自動的には何も実行しません。これは、それをトリガーするために必要なコードによって実行できる関数を返します。コールバックの実行を引き起こす変更をリッスンすることはありません。配列の値は、返される関数のインスタンスを制御するだけです。配列の値は、関数の実行のタイミングを制御しません。
主な使用例は、この関数を小道具として子コンポーネントに渡して、イベントハンドラーとして使用することです。 useCallback
を使用すると、イベントハンドラーとして使用するインライン関数を定義できます(したがって、関数が定義されているコンテキスト内の他の変数にアクセスできます)。レンダリングごとに子に一意のプロップを渡すことの欠点はありません。 。 2番目の引数の配列の値が変更されていない限り、以前のレンダリングで返されたものと同じ関数が返されます。したがって、子コンポーネントが純粋なコンポーネントである場合、常に一意のイベントハンドラー関数を受け取るために、単に再レンダリングを強制されることはありません。
useCallback
なし
const Parent = ()=> {
const [a, setA] = useState(null);
const eventHandler = ()=> {
// every render creates a unique instance of eventHandler
// even though it always does the same thing so long as 'a' hasn't changed
doSomethingWithA(a);
}
return <Child onClick={eventHandler}/>
}
useCallback
const Parent = ()=> {
const [a, setA] = useState(null);
const eventHandler = useCallback(()=> {
// A unique function instance is passed in to useCallback on every render, but
// eventHandler will be set to the first instance of this function
// (i.e. potentially an instance of the function that was passed to useCallback
// on a previous rendering) that was passed to useCallback
// for the current value of 'a'.
doSomethingWithA(a);
}, [a]);
return <Child onClick={eventHandler}/>
}
この記事 は、useCallback
およびその他のフックの使用例に関するReact docsよりも詳細を提供します。