👀useCallbackはとにかく使え! 特にカスタムフックでは
Loading...
カスタムフックを作る理由は、普通の関数を作る理由と全く同じであり、すなわち責務の分離とかカプセル化です。 一度カスタムフックとして分離された以上、インターフェースの内側のことはカスタムフック内で完結すべきです。 カスタムフックを使う側はカスタムフックの内側のことを知るべきではなく、その逆も然りです。
つまり、useToggleが返すtoggle関数が毎回変わる(=使う側に再レンダリングを強制する)のか、それともuseCallbackで囲まれていて基本的に変わらない(=使う側は再レンダリングを抑制できる)のかは、useToggleの仕様の一部としてuseToggle側が決めることです。
もしも「useToggleの返り値が毎回変わっていてSuperHeavyButtonが再レンダリングされてしまい困るからuseToggleにuseCallbackを追加した」というようなことが起こった場合は、それはuseToggleを使う側の都合を鑑みてuseToggleを仕様変更したということになります。 つまり、useToggleをコンポーネントロジックから分離して再利用可能にしたつもりが、結局使う側に振り回されてしまい再利用可能になっていなかったということです。 ご存知の通り、再利用可能性の低いものを無理に共通化し、そこにそれを使う側の都合を押し込んでいった場合、最終的にできるのはただのおいしいスパゲッティです。 せっかくカスタムフックを作るのだから、再利用可能性と独立性が高いものにするべきです。
そもそもReactの世界では、「値が違う」(===
ではない)ことが色々な処理のトリガーになります
React.memoもそうですし、useStateやコンテキストなども“違う”値が入ることが再レンダリングを引き起こします
ですから、違わないものは違わないと明確にする(===
になるようにする)ことには、単なるパフォーマンス最適化だけではなくロジック上の意味が付与されます
毎回違うものを返すということは、本当に毎回意味が異なるものを返していると受け取られます。 少なくとも、返されたものを使う側はそのように扱わなければいけません。 そうしないと、useMemoの依存リストを間違えて厄介なバグを生み出すことにも繋がりかねないからです。同じ意味のものを返すならば、useCallbackの力を借りてきちんと同じものを返しましょう。