riverpod
riverpod copied to clipboard
@rrousselGit @josh-burton I also encountered the same stack information, but I'm not sure if it's the same problem.
@rrousselGit @josh-burton I also encountered the same stack information, but I'm not sure if it's the same problem.
This is the smallest reproducible sample:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const SafeArea(child: MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var value1 = "123";
var value2 = "321";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
Expanded(
child: TestWidget.keyed(
value: value2,
),
),
Expanded(
child: TestWidget.keyed(
value: value1,
),
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
setState(() {
final tmp = value1;
value1 = value2;
value2 = tmp;
});
},
),
);
}
}
final provider = Provider<String>((ref) => throw UnimplementedError());
final asyncProvider =
AutoDisposeAsyncNotifierProvider<Notifier, String>(() => Notifier());
class Notifier extends AutoDisposeAsyncNotifier<String> {
@override
FutureOr<String> build() {
final data = ref.watch(provider);
return Future.delayed(const Duration(seconds: 2), () => "$data async");
}
}
class TestWidget extends StatelessWidget {
TestWidget.keyed({required this.value}) : super(key: ValueKey(value));
const TestWidget({super.key, required this.value});
final String value;
@override
Widget build(BuildContext context) {
return ProviderScope(
overrides: [provider.overrideWithValue(value)],
child: Consumer(
builder: (BuildContext context, WidgetRef ref, Widget? child) {
return ref.watch(asyncProvider).when(
data: (Object data) {
return Text(data.toString());
},
error: (Object error, StackTrace stackTrace) {
return Text('Error: $error');
},
loading: () => const Center(child: CircularProgressIndicator()));
}));
}
}
Clicking the button twice will reappear.
I found two key points in this example:
- It can be reproduced using
TestWidget.keyed()
, but notTestWidget()
, And TestWidget cannot be at the same children level - asyncProvider must be AutoDispose
Originally posted by @hcanyz in https://github.com/rrousselGit/riverpod/issues/2022#issuecomment-1783770010