以前、useCallbackについて調べた
ただ、このとき
メモ化されたコンポーネント(不必要なレンダーを避けるために参照の同一性を見るよう最適化されたコンポーネント)にコールバックを渡す場合に便利
という部分がよく理解できていなかった
そんなとき、関数オブジェクトの話を聞いて少し理解ができたのでまとめておく
useCallback単体で使っても意味がない
まず、useCallbackの第一引数をインライン関数で定義しておけば、関数定義を省略できるかとういうと、そういうわけではない
useCallbackを使った下のコードは
const onClick = useCallback(function cb() { doSomething(); }, [])
だいたいこれと同じになる(cbスコープが変わるので全く一緒じゃない)
const cb = function cb() { doSomething(); } const onClick = useCallback(cb, [])
つまり、関数定義は省略されないし、かつcbは呼び出し毎に関数オブジェクトが作られるのでuseCallback単体で使っても意味がない
というか、むしろ意味ないだけではなく、第二引数の依存リストに変更があるかをチェックする処理がある分無駄な記述ですらある
さらに、useCallbackは2回目に呼び出されたときに第一引数の関数を破棄して、1回目につくられた関数オブジェクトを返すということをしてくれる機能なので、1回目につくられた関数オブジェクトを覚えておくことも無駄ということだった
メモ化されたコンポーネントに渡す
本題の以下の話は
メモ化されたコンポーネント(不必要なレンダーを避けるために参照の同一性を見るよう最適化されたコンポーネント)にコールバックを渡す場合に便利
つまり、useCallback は不要に新しく関数インスタンスを作成することを抑制するので、「メモ化されたコンポーネントに関数を渡す場合に違うpropsと判断されないようにして、不要な再描画を減らしてくれるので便利」ということだと理解した
参考
https://kentcdodds.com/blog/usememo-and-usecallback