💨

StateError: Bad state: Cannot use "ref" after the widget was disposed.

2025/02/26に公開

StateError: Bad state: Cannot use "ref" after the widget was disposed.のエラー

開発中にタイトルのエラーに遭遇。ちょっと意味がわからなかったので調べてみた。
備忘録でかきこ

エラー内容

Flutter + Riverpod のコードでよく見るエラーメッセージで、「ウィジェット(あるいは ref を持つオブジェクト)が既にdispose(破棄)された後にrefを使おうとした」ときに発生するとのこと。

Riverpodのref.watch(...)やref.read(...)を、Widgetがdispose(破棄)された後でもコールバックや非同期処理で呼び出してしまうと起きるっぽい。

面白いのが公式でも同じエラー内容で記載があった。
https://riverpod.dev/docs/essentials/faq

他の関連記事を読むと、よく出るエラーらしくref.watch(...)を使っている場合に遭遇する率が高めです。

要はref.watch(...)で値監視して変化があったらUIに反映させたいけどその画面がすでに破棄されてるから駄目ですよっていうエラーになるのかなと。

ref.watch(...) or ref.read(...)

ref.watch

“常に最新の値を取りながら画面をリビルドしたい” 場合に使う。

例: 画面上にユーザー情報を表示するために、そのユーザー情報プロバイダをwatchする
→ 値が更新されるたびに画面を再描画。

ref.read

“今ある値を1回だけ使いたい、もしくはメソッド呼び出しだけしたい” 場合に使う

例: ボタンを押した瞬間にサインアウトを呼ぶ → UI 再描画は別に要らないから read で十分。
画面が閉じた後に watch を呼ぶとエラーが起きやすい

watchしてしまうとWidge とプロバイダが強く結びつき、「Widget が生存している」前提で動く。
画面を離れた後にまだwatchの呼び出しが動くと「もうこの画面はないから ref は使えない」という状態になる。

要するに、ref.watch の使いどこが間違えているんじゃない?

僕の場合は、UIの再描写は必要ないのに、ref.watchをつかっていたのでエラーになりました。

ref.readを使ったら解決。

公式でも同じエラー時はreadを使っているのとmountしているか判断してますね。

ref.watchで使っていて再描写ある場合はwatchの使いどころが違うかも!!!

以上!!!

Discussion