Flutterエンジニアの視点で考えるuseCallbackとuseMemo
ReactにおけるuseCallbackとuseMemoは、再描画の最適化を目的とした便利なHooksです。Flutterエンジニアとしての視点を活かして、useCallbackとuseMemoの違いについて整理します。
ReactとFlutterの再描画の違い
Reactの再描画
Reactでは、状態(state)やプロパティ(props)が変化するたびに、関連するコンポーネントが再描画(Re-render)されます。この再描画が発生すると、子コンポーネントにも影響を及ぼすため、パフォーマンスの低下を引き起こすことがあります。これを避けるため、ReactではuseCallbackやuseMemoを活用して最適化を図るのが一般的です。
Flutterのリビルド
一方、Flutterでは、build()メソッドが呼び出されてウィジェットツリーが再構築されますが、Flutter自体が効率的に設計されており、再ビルドのコストは比較的低いです。そのため、Reactほど再描画の最適化にシビアになる必要はないケースが多いです。
useCallbackとは?
useCallbackは、コールバック関数をメモ化するためのHookです。以下のように利用します。
const memoizedCallback = useCallback(() => {
// コールバック処理
}, [依存配列]);
特徴
目的: コールバック関数が毎回新しく生成されるのを防ぐ。
戻り値: メモ化されたコールバック関数。
利用シーン: 親コンポーネントから子コンポーネントに関数を渡す場合など。
Flutterでの類似例
Flutterでは、onPressed: () => handlePress()のように無名関数を渡すと、毎回新しい関数が生成されます。ただし、Flutterの場合、これがパフォーマンス問題につながることは少ないです。Reactでは、こうした挙動が不要な再描画の原因になることがあるため、useCallbackを用いて関数参照を安定させる必要があります。
useMemoとは?
useMemoは、計算結果をメモ化するためのHookです。以下のように利用します。
const memoizedValue = useMemo(() => {
return heavyComputation();
}, [依存配列]);
特徴
目的: コストの高い計算処理を必要なタイミングでのみ実行する。
戻り値: メモ化された計算結果。
利用シーン: 重い計算処理やオブジェクト生成を最適化したい場合。
Flutterでの類似例
Flutterでは、状態管理(BLoCやProviderなど)を利用して、計算結果をキャッシュすることがあります。これにより、依存する値が変わらない限り、同じ計算結果を使い続けるという考え方は、useMemoに近いものです。
ReactとFlutterの違いを踏まえた使い分け
どちらを使うべきか?
FlutterとReactの設計思想の違い
Flutterは、再描画コストを極力抑える設計になっているため、特別な最適化がなくてもパフォーマンスが安定しています。一方、Reactは状態変化やプロパティ変更が頻繁に発生するため、useCallbackやuseMemoを活用して再描画を細かく制御する必要があるケースが多いです。
まとめ
ReactのuseCallbackとuseMemoは、それぞれ「関数のメモ化」と「計算結果のメモ化」を目的としています。Flutterエンジニアにとっては、これらのHooksはFlutterのconstや状態管理での最適化に似た考え方を持つものと捉えると分かりやすいでしょう。
一方で、ReactはFlutterよりも再描画の影響を受けやすいため、メモ化の重要性が高いと言えます。Reactに触れる際には、「どのタイミングでメモ化が必要か」を意識しながら、適切なパフォーマンス最適化を実現していきましょう。