Flutterでflutter_hookのuseEffectを使用していると何も気にせず処理を入れると下記のようなエラーが表示されます。
日本語でのuseEffectの解説があまりなかったのでそちらについての解説をしていきたいと思います。
参考になれば幸いです。
目次
エラー内容
check Cannot listen to inherited widgets inside HookState.initState. Use HookState.build instead
HookState.initState 内で継承されたウィジェットをリッスンできません。代わりに HookState.build を使用してください。
【日本語訳】
参考コード(エラーになる)
void showTestDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return const TestPage();
},
);
}
// ここでエラー
useEffect(() {
showTestDialog();
return;
}, []);
ポイント
ポイントとしては、
- useEffett内でInheritedWidgetを呼ぶとエラーに
- 代わりにHookState.build を使用してね
のようなイメージです。
useEffett内でInheritedWidgetを呼ぶとエラーに
InheritedWidgetとは
そもそもinheritedWidgetとは下記のようなものです。
- ウィジェットツリー全体または一部に対してデータを効率的に共有するために使用される特別なウィジェット
- 実際のアプリケーションでは、InheritedWidgetを直接使用することは少ない
Riverpodの場合
Riverpodの場合は、
- InheritedWidgetの制限を克服するために設計された新しい状態管理の仕組み
- 特定のツリー外でのデータ共有が困難というデメリットがある
Flutter公式のInheritedWidget
InheritedWidget class - widgets library - Dart API
API docs for the InheritedWidget class from the widgets library, for the Dart programming language.
このInheritedWidgetをuseEffetct内で呼ぶとエラーになります。
代わりにHookState.build を使用してね
代わりに「HookState.build を使用してね」とのことでした
つまり
- useEffectやuseStateを正しく機能させるためには、build メソッドの呼び出し中にフックを使うべき
ということですね。
対策
WidgetsBinding.instance.addPostFrameCallbackを使う
WidgetsBinding.instance.addPostFrameCallbackを使用することで以下のようなことが可能になります。
- ウィジェットツリーが完全に構築された後に、特定の処理を実行するために利用されます
- ウィジェットのビルドが完了し、フレームが描画された後にコールバックを実行
- 必要な状態が確実に初期化されたタイミングで処理を実行できる
ただ、addPostFrameCallbackはあくまでウィジェットツリーの描画後に一度だけ処理を行いたい場合に使うのがベストです。
参考コード
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((_) {
showTestDialog();
});
return;
}, []);
状態の変化に基づいて処理を実行したい場合には、useEffectやbuild 内でのフック使用が適切です。別途他の解決方法についても追記できればと思います。
最後に
useEffectについて簡単に解説いたしました。さらに深ぼった記事についても別途記事として書けたらと思います。
ではまた。
コメント