4

I got an error

setState() or markNeedsBuild() called during build.

I develop an Web Dashboard with a Sidebar in Flutter (Web) using provider for state management.

Here is the full stack trace:

Restarted application in 243ms.
Gleap already initialized.
[GoRouter] Full paths for routes:
             => /login
[GoRouter] setting initial location /events
[GoRouter] Using MaterialApp configuration
User is signed in!
══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
The following assertion was thrown while dispatching notifications for SidebarViewModel:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<SidebarViewModel?> 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:
  _InheritedProviderScope<SidebarViewModel?>
The widget which was currently being built when the offending call was made was:
  LayoutBuilder
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49     throw_
packages/flutter/src/widgets/framework.dart 4549:11                              <fn>
packages/flutter/src/widgets/framework.dart 4563:14                              markNeedsBuild
packages/provider/src/inherited_provider.dart 577:5                              markNeedsNotifyDependents
packages/flutter/src/foundation/change_notifier.dart 351:24                      notifyListeners
packages/vamos_events_dashboard/ui/widgets/sidebar/sidebar_view_model.dart 27:5  expandSidebar
packages/vamos_events_dashboard/ui/pages/root_page.dart 18:57                    <fn>
packages/flutter/src/widgets/layout_builder.dart 119:70                          layoutCallback
packages/flutter/src/widgets/framework.dart 2605:19                              buildScope
packages/flutter/src/widgets/layout_builder.dart 153:5                           [_layout]
packages/flutter/src/rendering/object.dart 2246:59                               <fn>
packages/flutter/src/rendering/object.dart 1035:15                               [_enableMutationsToDirtySubtrees]
packages/flutter/src/rendering/object.dart 2246:7                                invokeLayoutCallback
packages/flutter/src/widgets/layout_builder.dart 228:7                           rebuildIfNecessary
packages/flutter/src/widgets/layout_builder.dart 316:5                           performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/custom_layout.dart 171:10                         layoutChild
packages/flutter/src/material/scaffold.dart 1055:7                               performLayout
packages/flutter/src/rendering/custom_layout.dart 240:7                          [_callPerformLayout]
packages/flutter/src/rendering/custom_layout.dart 410:14                         performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/proxy_box.dart 1462:11                            performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/layout_helper.dart 56:10                          layoutChild
packages/flutter/src/rendering/stack.dart 595:43                                 [_computeSize]
packages/flutter/src/rendering/stack.dart 622:12                                 performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/proxy_box.dart 3737:13                            performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/widgets/overlay.dart 804:14                                 performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/custom_paint.dart 552:11                          performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout
packages/flutter/src/rendering/object.dart 2135:7                                layout
packages/flutter/src/rendering/box.dart 2418:11                                  layout
packages/flutter/src/rendering/view.dart 170:7                                   performLayout
packages/flutter/src/rendering/object.dart 1973:7                                [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 999:17                                flushLayout
packages/flutter/src/rendering/binding.dart 513:19                               drawFrame
packages/flutter/src/widgets/binding.dart 884:13                                 drawFrame
packages/flutter/src/rendering/binding.dart 378:5                                [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1175:15                              [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1104:9                               handleDrawFrame
packages/flutter/src/scheduler/binding.dart 881:7                                <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19          internalCallback
The SidebarViewModel sending notification was:
  Instance of 'SidebarViewModel'
════════════════════════════════════════════════════════════════════════════════════════════════════

Here are the three relevant classes:

RootPage:

class RootPage extends StatelessWidget {
  const RootPage({required this.widget});

  final Widget widget;

  @override
  Widget build(BuildContext context) {
    final SidebarViewModel sidebarViewModel = context.read<SidebarViewModel>();

    return Scaffold(
      body: LayoutBuilder(
        builder: (_, BoxConstraints constraints) {
          constraints.maxWidth > 1100 ? sidebarViewModel.expandSidebar() : sidebarViewModel.collapseSidebar();
          return Row(children: [const Sidebar(), Expanded(child: widget)]);
        },
      ),
    );
  }
}

Sidebar:

class Sidebar extends StatelessWidget {
  const Sidebar({super.key});

  @override
  Widget build(BuildContext context) {
    final SidebarViewModel sidebarViewModel = context.watch<SidebarViewModel>();
    // final SidebarViewModel sidebarViewModel = Provider.of<SidebarViewModel>(context, listen: false);

    return SizedBox(
      width: sidebarViewModel.isExpanded ? 250 : 90,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            SidebarEntry(
              title: 'Profil',
              icon: Icons.account_circle_outlined,
              onTap: () {
                if (sidebarViewModel.selectedItem != SidebarItem.profile) {
                  sidebarViewModel.selectItem(SidebarItem.profile);
                  context.go(ProfilePage.route);
                }
              },
              isSelected: sidebarViewModel.selectedItem == SidebarItem.profile,
            ),
            SidebarEntry(
              title: 'Organisation',
              icon: Icons.business_center_outlined,
              onTap: () {
                if (sidebarViewModel.selectedItem != SidebarItem.organization) {
                  sidebarViewModel.selectItem(SidebarItem.organization);
                  context.go(OrganizationPage.route);
                }
              },
              isSelected: sidebarViewModel.selectedItem == SidebarItem.organization,
            ),
            SidebarEntry(
              title: 'Veranstaltungen',
              icon: Icons.calendar_month_rounded,
              onTap: () {
                if (sidebarViewModel.selectedItem != SidebarItem.events) {
                  sidebarViewModel.selectItem(SidebarItem.events);
                  context.go(EventsPage.route);
                }
              },
              isSelected: sidebarViewModel.selectedItem == SidebarItem.events,
            ),
            const Spacer(),
            SidebarEntry(
              title: 'Abmelden',
              icon: Icons.logout,
              onTap: () => context.read<AuthService>().signOut(),
            ),
          ],
        ),
      ),
    );
  }
}

SidebarViewModel:

enum SidebarItem { profile, organization, events }

class SidebarViewModel with ChangeNotifier {
  SidebarViewModel();

  SidebarItem _selectedItem = SidebarItem.events;
  bool _isExpanded = false;

  SidebarItem get selectedItem => _selectedItem;
  bool get isExpanded => _isExpanded;

  void selectItem(SidebarItem item) {
    _selectedItem = item;
    notifyListeners();
  }

  void toggleSidebarExpansion() {
    _isExpanded = !_isExpanded;
    notifyListeners();
  }

  void expandSidebar() {
    if (_isExpanded) return;
    _isExpanded = true;
    notifyListeners();
  }

  void collapseSidebar() {
    if (!_isExpanded) return;
    _isExpanded = false;
    notifyListeners();
  }
}

I'd be glad if anyone could help me solve this error. The error appears only if the "expandSidebar" or "collapseSidebar" methods are called in the ViewModel. In other words: when I make the web window smaller or bigger, it triggers the build Method in the RootPage and then either the expand- or collapse-Sidebar methods.

5
  • @Hamed added the code directly, now (instead of Hastebin). Commented Jan 29, 2023 at 1:38
  • I suppose wrapping constraints.maxWidth > 1100 ? sidebarViewModel.expandSidebar() : sidebarViewModel.collapseSidebar(); in SchedulerBinding.instance.addPostFrameCallback probably will solve your issue. WidgetsBinding.instance.addPostFrameCallback((_) {constraints.maxWidth > 1100 ? sidebarViewModel.expandSidebar() : sidebarViewModel.collapseSidebar()}); Commented Jan 29, 2023 at 3:07
  • Problem is occuring because of context.watch so replace it with context.read Commented Jan 29, 2023 at 5:00
  • @Prashant I used your solution with post frame callback and it worked, thanks! Where should I replace context.read()? In the RootPage, I already use the .read instead of .watch method Commented Jan 29, 2023 at 9:55
  • You should do context.read in initstate method Commented Jan 29, 2023 at 12:31

3 Answers 3

8

The error means that somewhere in your build() method either setState() or markNeedsBuild() gets called. So the build() function basically would call itself again and again while it hasn't completed.

An easy fix might be to use an post frame callback with

// build method of your RootPage widget
@override
  Widget build(BuildContext context) {
    final SidebarViewModel sidebarViewModel = context.read<SidebarViewModel>();

    return Scaffold(
      body: LayoutBuilder(
        builder: (_, BoxConstraints constraints) {
          WidgetsBinding.instance!.addPostFrameCallback((_) {
              // executes after build
              constraints.maxWidth > 1100 
                  ? sidebarViewModel.expandSidebar() 
                  : sidebarViewModel.collapseSidebar();
          });
          return Row(children: [const Sidebar(), Expanded(child: widget)]);
        },
      ),
    );
  }
Sign up to request clarification or add additional context in comments.

Comments

5

Note: I was still getting this error while using

if (mounted) {
  setState(() {});
}

I replaced it with the following code and the error was gone.

if (mounted) {
      SchedulerBinding.instance.addPostFrameCallback((_) {
        setState(() {});
      });
    }

Nothing else worked for me and did not know why.

Comments

0

If you're encountering the setState() or markNeedsBuild() called during build error while using the Provider package in your Flutter application, it typically means that you are trying to call notifyListeners() or update the UI during the build process, which is not allowed. This can cause an infinite loop and result in unexpected behavior. It might happen beacuse you are using consumer widget in a statefull class and inside consumer you might be using setState() method.

Solution 1
Ensure that any state updates and notifyListeners() calls are made outside of the widget's build.

class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
  sup

er.initState();
      WidgetsBinding.instance.addPostFrameCallback((_) {
        Provider.of<CurrencyHistoryProvider>(context, listen: false).fetchCurrencyHistory();
     });
    }

  @override
  Widget build(BuildContext context) {
   return Container(); // your other code here
  }
}

Solution 2
You can use FutureBuilder or StreamBuilder too. The Key is to make sure you do not use setState() or these builder widgets inside consumer widgets such that Second build is run before the first has finished

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.