【Flutter の例外】Tried to modify a provider while the widget tree was building. 【解決】

Flutter Advent Calendar 2022」に参加させて頂きます!一応作成日にマッチさせてるし、開いている、クレームは言われないよね?。12日目です。

状況

RiverpodのConsumerStatefulWidgetを使用して状態管理をしている。initSateの中でStateProviderの値を書き換えようとすると、以下のエラーが発生した。

Unhandled Exception: Tried to modify a provider while the widget tree was building.

問題点

Widget Treeの生成中などライフサイクル内で状態を変更しようとした点が悪い。ライフサイクルの処理が完了してから、状態の変更をしないといけない

解決方法

「WidgetsBinding.instance.addPostFrameCallback」を使って、画面の描画が始まったタイミングで状態の変更をする。

WidgetsBinding.instance.addPostFrameCallback((_) {
  ref.read(aProvider.notifier).state = 1;
});

余談

毎回 Widgetなんだったけなぁ、と思い出すのに苦労するので、アウトプットして覚えれたらいいなぁ。

エラーのメッセージ全文

エラーメッセージから、このような処理をしなければならないのは、以下の通りとある。

  • build
  • initState
  • dispose
  • didUpdateWidget
  • didChangeDepedencies

特に「build」内ではやりがちなので、ボタンのonPress内に移動しろ、とも書いてある。

Reloaded 1 of 1302 libraries in 432ms.
E/flutter (25473): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Tried to modify a provider while the widget tree was building.
E/flutter (25473): If you are encountering this error, chances are you tried to modify a provider
E/flutter (25473): in a widget life-cycle, such as but not limited to:
E/flutter (25473): - build
E/flutter (25473): - initState
E/flutter (25473): - dispose
E/flutter (25473): - didUpdateWidget
E/flutter (25473): - didChangeDepedencies
E/flutter (25473):
E/flutter (25473): Modifying a provider inside those life-cycles is not allowed, as it could
E/flutter (25473): lead to an inconsistent UI state. For example, two widgets could listen to the
E/flutter (25473): same provider, but incorrectly receive different states.
E/flutter (25473):
E/flutter (25473):
E/flutter (25473): To fix this problem, you have one of two solutions:
E/flutter (25473): - (preferred) Move the logic for modifying your provider outside of a widget
E/flutter (25473): life-cycle. For example, maybe you could update your provider inside a button's
E/flutter (25473): onPressed instead.
E/flutter (25473):
E/flutter (25473): - Delay your modification, such as by encasuplating the modification
E/flutter (25473): in a `Future(() {...})`.
E/flutter (25473): This will perform your upddate after the widget tree is done building.
E/flutter (25473): #0 _UncontrolledProviderScopeElement._debugCanModifyProviders (package:flutter_riverpod/src/framework.dart:343:7)
E/flutter (25473): #1 ProviderElementBase._notifyListeners. (package:riverpod/src/framework/element.dart:483:34)