hooksAPIの中で、useCallbackの使い所がいまいちわからなかったので検証してみました。
結果だけ知りたい人
自コンポーネントだけで使うコールバック関数の場合は使う必要なし。
コールバック関数を渡す子コンポーネントでmemo化などをしてない限り使う必要なし。
検証
実際に検証してみました。
まずは、useCallbackを使わないパターンです
フォームに値を入れたり、UPを押したりしてレンダリングを確認してみます。
親コンポーネント
export default function CounterApp () { const [counter, setCounter] =React.useState(0) const [value, setValue] =React.useState("") const handleIncrement=()=> { setCounter(state=>state+1) } // useCallbackを使ったもの // const handleIncrement=React.useCallback(()=> { setCounter(state=>state+1) }, [setCounter]) console.log("render counterApp") return ( <div> <h1>Counter</h1> <input value={value} onChange={(e)=>setValue(e.target.value)}/> <div>{counter}</div> <Wrapper increment={handleIncrement}/> </div> ) }
インクリメントするだけのボタンコンポーネント
メモ化しているのでpropsに変更がなければ再レンダーされません。
const Counter: React.FC<{increment: () => void}> = React.memo((props) =>{ console.log("render counter") return ( <div> <button onClick={props.increment}>UP</button> </div> ) })
Counterコンポーネントをラップするコンポーネント
const Wrapper: React.FC<{increment: () => void}> = (props) => { console.log("render wrapper") return<Counter increment={props.increment}/> }
このコンポーネントのフォームに値を入れると…
memo化したcounterコンポーネントもレンダリングされてしまっています。
次にuseCallbackを使ったインクレメント関数を渡してみます。
CounterAppコンポーネントの関数をuseCallbackにします。
const handleIncrement = React.useCallback(() => { setCounter(state=>state+1) },[setCounter])
これでフォームに値を入れてみると…
うまくいきました。
メモ化されてるcounterコンポーネントのレンダリングがされていません。
フロントエンド開発でお困りのことはありませんか?
フロントエンドの開発支援を行っています。
・Reactの開発をお願いしたい
・コーディング作業を依頼したい
・javascriptライブラリを作って欲しい。
上記以外にも何かありましたらお気軽にお問い合わせください。