rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
5.82k stars 888 forks source link

`Unhandled Exception: setState() or markNeedsBuild() called during build.` when combining overrides and async providers #3498

Open ValentinVignal opened 3 weeks ago

ValentinVignal commented 3 weeks ago

Describe the bug

I'm using flutter_riverpod: ^2.5.1

I'm having the error Unhandled Exception: setState() or markNeedsBuild() called during build. when I combine overriddes and async providers (StreamProvider or FutureProvider).

To Reproduce

Run flutter run on the code sample:

Code sample ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; void main() { runApp( const ProviderScope( child: MyApp(), ), ); } class MyApp extends ConsumerWidget { const MyApp({ super.key, }); @override Widget build(BuildContext context, WidgetRef ref) { return MaterialApp( home: ProviderScope( overrides: [ parameterProvider.overrideWithValue(null), ], child: const Scaffold( body: Column( children: [ Widget1(), Widget2(), ], ), ), ), ); } } class Widget1 extends ConsumerWidget { const Widget1({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final version = ref.watch(combinedProvider) != null; return Text('version $version'); } } class Widget2 extends ConsumerWidget { const Widget2({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final combined = ref.watch(combinedProvider) != null; final provider = ref.watch(secondProvider) != null; return Text('notifier $provider, combined $combined'); } } final parameterProvider = Provider.autoDispose((ref) => null); final futureProvider = FutureProvider.autoDispose((ref) async { return 42; }); final secondProvider = Provider.autoDispose((ref) { return ref.watch(futureProvider).valueOrNull; }, dependencies: [futureProvider]); final combinedProvider = Provider.autoDispose( (ref) { return ref.watch(parameterProvider) ?? ref.watch(secondProvider); }, dependencies: [parameterProvider, secondProvider], ); ```
Logs ```console [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: setState() or markNeedsBuild() called during build. This Widget1 widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase. The widget on which setState() or markNeedsBuild() was called was: Widget1 The widget which was currently being built when the offending call was made was: Widget2 #0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5033:9) #1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5045:6) #2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/consumer.dart:566:20) #3 ProviderBase.addListener. (package:riverpod/src/framework/provider_base.dart:98:41) #4 _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10) #5 ProviderElementBase._notifyListeners. (package:riverpod/src/framework/element.dart:525:28) #6 ResultData.map (package:riverpod/src/result.dart:74:16) #7 ProviderElementBase._notifyListeners (package:riverpod/src/framework/element.dart:519:14) #8 ProviderElementBase._performBuild (package:riverpod/src/framework/element.dart:358:7) #9 ProviderElementBase.flush (package:riverpod/src/framework/element.dart:307:7) #10 ProviderElementBase.readSelf (package:riverpod/src/framework/element.dart:776:5) #11 _ProviderStateSubscription.read (package:riverpod/src/framework/provider_base.dart:181:28) #12 ConsumerStatefulElement.watch (package:flutter_riverpod/src/consumer.dart:568:8) #13 Widget2.build (package:flutter_app_stable/main.dart:53:26) #14 _ConsumerState.build (package:flutter_riverpod/src/consumer.dart:476:19) #15 StatefulElement.build (package:flutter/src/widgets/framework.dart:5583:27) #16 ConsumerStatefulElement.build (package:flutter_riverpod/src/consumer.dart:539:20) #17 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5471:15) #18 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11) #19 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7) #20 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2895:19) #21 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:984:21) #22 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5) #23 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1325:15) #24 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9) #25 SchedulerBinding.scheduleWarmUpFrame. (package:flutter/src/scheduler/binding.dart:978:7) #26 Timer._createTimer. (dart:async-patch/timer_patch.dart:18:15) #27 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19) #28 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5) #29 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12) ```

Expected behavior A clear and concise description of what you expected to happen.