riverpod icon indicating copy to clipboard operation
riverpod copied to clipboard

Throws Bad state: Cannot use "ref" after the widget was disposed, when using ref in dispose callback, even though widget is still mounted

Open saibotma opened this issue 8 months ago • 2 comments

Describe the bug Throws Bad state: Cannot use "ref" after the widget was disposed., when using ref in dispose callback, even though widget is still mounted.

The widget is obviously not disposed yet, because mounted still returns true and super.dispose did not run, yet. Or am I missing something?

To Reproduce

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isDisposed = false;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration(seconds: 2), () {
      setState(() {
        isDisposed = true;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return ProviderScope(
      child: MaterialApp(home: isDisposed ? Container() : Screen1()),
    );
  }
}

class Screen1 extends ConsumerStatefulWidget {
  const Screen1({super.key});

  @override
  ConsumerState<Screen1> createState() => _Screen1State();
}

class _Screen1State extends ConsumerState<Screen1> {
  @override
  Widget build(BuildContext context) {
    return Placeholder();
  }

  @override
  void dispose() {
    print(mounted);
    ref.read(provider);
    super.dispose();
  }
}

final provider = Provider.autoDispose((ref) => 1);

Using commit 5bf55e19a4a5254524bfa88633c188c5ca07eb1f.

Expected behavior Should print true and then not throw.

saibotma avatar Jun 04 '25 06:06 saibotma

#1610

snapsl avatar Jun 04 '25 20:06 snapsl

Thanks. I guess the error message could be improved, then. Accessing context in dispose gives the following error:

Looking up a deactivated widget's ancestor is unsafe.

At this point the state of the widget's element tree is no longer stable.

To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

Would be great if Riverpod threw something similar, because as far as I understand the widget is not disposed, yet, but only deactivated at this point in time.

saibotma avatar Jun 05 '25 07:06 saibotma