The following assertion was thrown building ItemCard(dirty): setState() or markNeedsBuild() called during build

560

The onPress function in the GestureDetector is being invoked immediately.

There are two ways you can go about fixing the problem.

  1. Remove the call to the function, by removing the ()
  2. Wrap the press function in an anonymous function, so that I can be invoked later when the user actually performs the action, this is usually done when you need to evaluate a variable, For Example in the onChanged handler of TextField or TextFormField

Check the code snippets below.

Example of Method 1.

@override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: press,
      child: ...
   )
}

Example of Method 2:

@override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => press(),
      child: ...
   )
}
Share:
560
Hassan Waqqaf
Author by

Hassan Waqqaf

Updated on December 30, 2022

Comments

  • Hassan Waqqaf
    Hassan Waqqaf over 1 year

    I'm new to flutter, and I'm trying to build an Online Shopping app as my graduation project.

    Every time I run the app it goes straight the "Item Card" method and through it to "Details Screen", even though it's supposed to only go there on pressing through the Navigator widget.

    It's also marking the Item Card as a dirty child (I don't quite understand what that means and how to revert it to being a normal child).

       Error message: The following assertion was thrown building ItemCard(dirty):
    setState() or markNeedsBuild() called during build.
    

    I hope I explained the error well enough.. here is the code, First is the Body class, then Item Card class, and then Details Screen class:

        class Body extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: kDefaultPaddin),
              child: Text(
                "Mobiles",
                style: Theme.of(context)
                    .textTheme
                    .headline5!
                    .copyWith(fontWeight: FontWeight.bold),
              ),
            ),
            Categories(),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: kDefaultPaddin),
                child: GridView.builder(
                    itemCount: productz.length,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      mainAxisSpacing: kDefaultPaddin,
                      crossAxisSpacing: kDefaultPaddin,
                      childAspectRatio: 0.75,
                    ),
                    itemBuilder: (context, index) => ItemCard(
                          productz: productz[index],
                          press: () => Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (context) => DetailsScreen(
                                  productz: productz[index],
                                ),
                              )),
                        )),
              ),
            ),
          ],
        );
      }
    }
    
    class ItemCard extends StatelessWidget {
      final Productz productz;
      final Function press;
      const ItemCard({
        Key? key,
        required this.productz,
        required this.press,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: press(),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Expanded(
                child: Container(
                  padding: EdgeInsets.all(kDefaultPaddin),
    
                  decoration: BoxDecoration(
                    color: Colors.white12,
                    borderRadius: BorderRadius.circular(16),
                  ),
                  child: Hero(
                    tag: "${productz.id}",
                    child: Image.asset(productz.item_image),
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: kDefaultPaddin / 4),
                child: Text(
                  // products is out demo list
                  productz.item_name,
                  style: TextStyle(color: kTextLightColor),
                ),
              ),
              Text(
                "\$${productz.item_price}",
                style: TextStyle(fontWeight: FontWeight.bold),
              )
            ],
          ),
        );
      }
    }
    
    class DetailsScreen extends StatelessWidget {
      final Productz productz;
    
      const DetailsScreen({Key? key, required this.productz}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          // each product have a color
          backgroundColor: Colors.white12,
          appBar: buildAppBar(context),
          body: Body(productz: productz),
        );
      }
    
      AppBar buildAppBar(BuildContext context) {
        return AppBar(
          backgroundColor: Colors.white12,
          elevation: 0,
          leading: IconButton(
            icon: Icon(Icons.arrow_back,
              size: 30,
              color: Colors.white,
            ),
            onPressed: () => Navigator.pop(context),
          ),
          actions: <Widget>[
            IconButton(
              icon: Icon(FontAwesomeIcons.search),
              onPressed: () {},
            ),
            IconButton(
              icon: Icon(FontAwesomeIcons.shoppingCart),
              onPressed: () {},
            ),
            SizedBox(width: kDefaultPaddin / 2)
          ],
        );
      }
    }