-
-
Notifications
You must be signed in to change notification settings - Fork 956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AutoDisposeProvider does not recreate value in nested ScopedProvider #1943
Comments
And what's the issue / expected behavior? |
ah, I updated the code and description. The issue is the exception 'Bad state: Trying to read an uninitialized value.' is thrown. |
What's the stacktrace? |
Added stacktrace. |
Same issue here, I added a temporary ref.keepAlive() in my StateNotifierProvider. |
I reproduced this with the following test. test('3-depth autoDispose', () async {
final a = createContainer();
final b = createContainer(parent: a);
final c = createContainer(parent: b);
var count = 0;
final autoDisposeProvider = Provider.autoDispose((ref) {
count += 1;
ref.onDispose(() {
count -= 1;
});
return 3;
});
var subscription = c.listen(
autoDisposeProvider,
(previous, next) {},
fireImmediately: true,
);
await a.pump();
expect(count, 1);
subscription.close();
await a.pump();
expect(count, 0);
subscription = c.listen(
autoDisposeProvider,
(previous, next) {},
fireImmediately: true,
);
await a.pump();
expect(count, 1);
subscription.close();
await a.pump();
expect(count, 0);
}); So my investigation is this. I can make the test pass by commenting out the conditional, but I can't sure it is right way. |
Here's another example of this issue that is based on the DartPad Riverpod example: Example code// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// This is a reimplementation of the default Flutter application
// using riverpod.
void main() {
runApp(
// Adding ProviderScope enables Riverpod for the entire project
const ProviderScope(child: MyApp()),
);
}
/// Providers are declared globally and specify how to create a state
final counterProvider = StateProvider((ref) => 0);
// BUG - Auto disposed provider tracks the above counter
final derivedProvider = Provider.autoDispose((ref) =>
ref.watch(counterProvider));
// BUG - Use the above provider
class DerivedCounter extends ConsumerWidget {
@override Widget build(BuildContext context, WidgetRef ref) {
final derivedCount = ref.watch(derivedProvider);
return Text('$derivedCount <-- Should track counter!!');
}
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod example'),
),
// BUG - At least 2 additional scopes cause the issue
body: ProviderScope(
child: ProviderScope(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
// BUG - Usage of the provider is transient
// This value should track the counter!!!
if (count != 1) DerivedCounter(),
Consumer(
builder: (context, ref, _) {
return Text(
'$count',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
],
),
))),
floatingActionButton: FloatingActionButton(
key: const Key('increment_floatingActionButton'),
// The read method is a utility to read a provider without listening to it
onPressed: () => ref.read(counterProvider.notifier).state++,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
} Copy this code into DartPad and run - clicking the button to increment the count should also update the derived count. As reported above, the issue requires This issue was difficult for us to track down since not all of our code paths create the multiple nested scopes that cause the failure. |
I think I'm also running into something similar. Multiple levels of nested providerscopes, and some providers intermittently are not updating. |
Pretty sure I'm facing the same issue too, a |
I am also facing this issue. @rrousselGit were you able to reproduce the issue, or do you need help in reproducing? |
@rrousselGit Bumping this issue Facing a similar issue to this as well For my case scenario, it also involves nesting of In each news card, there is a bookmark button, which will perform an API call to update the value of
|
my issue #2198 could be related to this? |
@ykaito21 Yes. It is the same issue |
Describe the bug
Exception 'Bad state: Trying to read an uninitialized value.' is thrown.
To Reproduce
With the following code, tap 'Toggle Button' more than three times.
When tapping three or five times, the value '0' is shown but "created!" log is not. And when tapping four or six times, "created!" and "disposed" are shown at the nearly same time.
After tapping three or six times, the exception is thrown if the button in the
SampleWidget
is clickedExpected behavior
Update provider value.
Stacktrace:
The text was updated successfully, but these errors were encountered: