👏

Flutter_hooksのuseListenableとuseEffectの違い@初心者

2024/10/07に公開

Flutter hooks のuseListenable と useEffect の違い

下記パッケージを利用している際に、状態管理でuseListenable と useEffect の違いが曖昧だったため、かきこ。

https://pub.dev/packages/flutter_hooks

useListenable とは

useListenable は、Flutter Hooks の一つで、Listenable オブジェクト(例えば TabController、AnimationController、ValueNotifier など)を監視し、その状態が変化したときにウィジェットを再ビルドします。

  • 自動的なリスナー登録と解除:

useListenable を使用すると、Listenable に対するリスナーの登録と解除が自動的に行われます。

ウィジェットの再ビルド:
Listenable の状態が変化したときに、ウィジェットが再ビルドされます。

final tabController = useTabController(initialLength: 3);
useListenable(tabController);

上記のコードでは、tabController の状態(例えば、選択されているタブのインデックス)が変化したときに、ウィジェットが自動的に再ビルドされます。
addListener や removeListener を手動で管理する必要がありません。

どんなときに使うか

Listenable の状態変化に応じて、UI を更新したい場合。
例:タブの選択状態に応じて、ウィジェットの表示を変えたいとき。

useEffect とは

useEffect は、依存関係の変化に応じて、副作用(サイドエフェクト)を実行するためのフックです。React の useEffect に似ています。

  • 主な特徴
    副作用の実行:
    ウィジェットのビルドとは直接関係のない処理(データのフェッチ、リスナーの登録、タイマーの開始など)を実行します。

依存関係の管理:
指定した依存関係が変化したときに、副作用の関数が再実行されます。

useEffect(() {
  // 副作用の処理
  return () {
    // クリーンアップ処理
  };
}, [依存関係]);

副作用の関数:
第一引数として、副作用を実行する関数を渡します。

クリーンアップ関数:
副作用の関数内で return することで、ウィジェットが破棄されるときにクリーンアップ処理を実行できます。

依存関係:
第二引数として、リスト形式で依存関係を指定します。この依存関係が変化したときに、副作用が再実行されます。

どんなときに使うか

初回ビルド時や依存関係が変化したときに、一度だけ特定の処理を実行したい場合。
例:データの取得、リスナーの手動登録、タイマーの開始など。

setStatu({})に近い感覚です。

useListenable と useEffect の違い

  • 主な目的の違い

useListenable:
UI の更新が主な目的。
Listenable の変化に応じて、ウィジェットを再ビルドします。

useEffect:
副作用の実行が主な目的。
ウィジェットのビルドサイクルとは別に、特定の処理を実行します。

動作の違い

  • useListenable:

自動的にリスナーを登録し、Listenable の状態が変化したときにウィジェットを再ビルド。
手動でのリスナー管理が不要。

  • useEffect:

依存関係が変化したときに、一度だけ副作用の関数を実行。
リスナーの登録や解除を手動で行う必要がある場合がある。

例としてtabの切り替えの際の処理を行おうとすると

/// useListenable

final tabController = useTabController(initialLength: 3);
useListenable(tabController); /// ここだけでOK

// ウィジェットのビルド
Widget build(BuildContext context) {
  final currentIndex = tabController.index;
  // currentIndex を使用してウィジェットを構築
}

/// useEffect

final tabController = useTabController(initialLength: 3);

useEffect(() {
  void listener() {
    // 何らかの処理
  }
  tabController.addListener(listener);
  return () {
    tabController.removeListener(listener);
  };
}, [tabController]);

useEffect を使う場合、リスナーの登録と解除を自分で行う必要があります。
また、記載内容が増える。

まとめ

  • useListenable:

メリット:
シンプルに Listenable の変化を監視して、ウィジェットを再ビルドできる。
リスナーの登録・解除を自動化。

  • 使うべき場合:

Listenable の状態変化に応じて UI を更新したいとき。


  • useEffect:

メリット:
依存関係の変化に応じて、一度だけ副作用の処理を実行できる。
柔軟な副作用の管理が可能。

  • 使うべき場合:

初期化処理やリスナーの手動管理、非同期処理の開始など、副作用が必要なとき。
選択のポイント:

UI の更新が目的で、Listenable の状態変化に応じてウィジェットを再ビルドしたい場合は、useListenable を使用するのが適切です。
副作用の実行が目的で、依存関係の変化に応じて一度だけ処理を実行したい場合は、useEffect を使用します。

以上

Discussion