Home > OS >  "setState() or markNeedsBuild() called during build" how to resolve this?
"setState() or markNeedsBuild() called during build" how to resolve this?

Time:01-26

Here is the full error message.

The following assertion was thrown building MealDeatialRoute(dirty, dependencies: [MediaQuery, _ModalScopeStatus]): setState() or markNeedsBuild() called during build.

This MyApp 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: MyApp

And Here is a code of main.

import 'package:flutter/material.dart';

import './routes/main_tab_route.dart';
// import './routes/favorites_tab_route.dart';
// import './routes/filter_tab_route.dart';
import './routes/category_meal_route.dart';
import './routes/meal_detial_route.dart';
import './routes/select_filter_route.dart';

import './dummy_data.dart';
import './model/meal.dart';

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

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var _filters = {
    'gluteenFree': false,
    'lactoseFree': false,
    'vegan': false,
    'vegetarian': false,
  };

  final List<Meal> _avialableMeal = dummyMeals;

  final List<Meal> _favoriteMeal = [];

  void _toggleFavorite(String id) {
    int existIndex = _favoriteMeal.indexWhere((meal) => meal.id == id);

    if (existIndex >= 0) {
      setState(() {
        _favoriteMeal.removeAt(existIndex);
      });
    } else {
      setState(() {
        _favoriteMeal.add(dummyMeals.firstWhere((meal) => meal.id == id));
      });
    }
  }

  bool _isMealFavorite(String id) {
    return _favoriteMeal.any((meal) => meal.id == id);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Meal App',
      theme: ThemeData(
        primaryColor: Colors.red,
        colorScheme:
            ColorScheme.fromSwatch().copyWith(secondary: Colors.amberAccent),
        appBarTheme: const AppBarTheme(
          titleTextStyle: TextStyle(
            fontSize: 23,
            fontWeight: FontWeight.bold,
          ),
        ),
        textTheme: const TextTheme(
          titleMedium: TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => MainTabRoute(_favoriteMeal),
        SelectFilterRoute.routeName: (context) => SelectFilterRoute(),
        CategoreyMealRoute.routeName: (context) => CategoreyMealRoute(),
        MealDeatialRoute.routeName: (context) =>
            MealDeatialRoute(_toggleFavorite, _isMealFavorite),
      },
    );
  }
}

And an error is cause by MealDeatailRoute.dart file so which is below

import 'package:flutter/material.dart';
import 'package:mealapp/dummy_data.dart';

class MealDeatialRoute extends StatelessWidget {
  static const routeName = '/meal-detail';

  final Function toggleFavorite;
  final Function isFavorite;

  MealDeatialRoute(this.isFavorite, this.toggleFavorite);

  @override
  Widget build(BuildContext context) {
    final mealId = ModalRoute.of(context)!.settings.arguments as String;

    final meal = dummyMeals.firstWhere((meal) => meal.id == mealId);

    AppBar appBar = AppBar(
      title: Text(meal.title),
    );

    Widget _buildTitle(String title) {
      return Padding(
        padding: const EdgeInsets.all(10),
        child: Text(
          title,
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
      );
    }

    Widget _buildContainer(Widget child) {
      return Container(
        margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
        height: 200,
        decoration: BoxDecoration(
          border: Border.all(color: Colors.black, width: 1),
        ),
        child: child,
      );
    }

    final mediaQuery = MediaQuery.of(context);

    final contentSize = mediaQuery.size.height -
        mediaQuery.padding.top -
        appBar.preferredSize.height;

    return Scaffold(
      appBar: appBar,
      body: Column(
        children: [
          Image.network(
            meal.imageUrl,
            fit: BoxFit.cover,
            height: contentSize * 0.4,
          ),
          SizedBox(
            height: contentSize * 0.6,
            child: SingleChildScrollView(
              child: Column(
                children: [
                  _buildTitle('Ingreidants'),
                  _buildContainer(ListView(
                    children: meal.ingredients
                        .map(
                          (inData) => Container(
                            margin: const EdgeInsets.all(10),
                            padding: const EdgeInsets.all(10),
                            decoration: BoxDecoration(
                                color: Colors.amber,
                                borderRadius: BorderRadius.circular(10)),
                            child: Text(inData),
                          ),
                        )
                        .toList(),
                  )),
                  _buildTitle('Steps'),
                  _buildContainer(
                    ListView.builder(
                      itemCount: meal.steps.length,
                      itemBuilder: ((context, index) {
                        return Column(
                          children: [
                            ListTile(
                              leading: CircleAvatar(
                                child: Text('# ${index   1}'),
                              ),
                              subtitle: Text(meal.steps[index]),
                            ),
                            const Divider(),
                          ],
                        );
                      }),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          toggleFavorite(mealId);
        },
        child: Icon(
          // Icons.star,
          isFavorite(mealId) ? Icons.star : Icons.star_border,
        ),
      ),
    );
  }
}

I also find some this types of error on this site but I didn't figured it out why this happened so why this error showing?

CodePudding user response:

You are using positional constructurctor, this makes consfusion on MealDeatialRoute consturctor.

You are reading like

MealDeatialRoute(this.isFavorite, this.toggleFavorite);

But on _AppState, passing on wrong order.

 MealDeatialRoute.routeName: (context) =>
            MealDeatialRoute(_toggleFavorite, _isMealFavorite),

Which will be

MealDeatialRoute(_isMealFavorite, _toggleFavorite),

To avoid this error in the future, try using named constructor.

  • Related