Search code examples
flutterdarttoastsnackbar

ScaffoldMessenger.of(context).showSnackBar() doesn't work when called directly inside a widget build function


While looking for examples for using flutter SnackBar with ScaffoldMessenger, I only found usages with onPressed function:

    Widget build(BuildContext context) {
        return Container(
            child: ElevatedButton(
              child: ...,
              onPressed: () => _showToast(context),
            ));
      }
    
      void _showToast(BuildContext context) {
        final scaffold = ScaffoldMessenger.of(context);
        scaffold.showSnackBar(
          SnackBar(content: const Text('Added to favorite')),
        );
      }
    }

but non of the examples explain why one have to use it with onPressed only, so I tried it my self and used in directly inside the build function:

         Widget build(BuildContext context) {
           _showToast(context);   <---
           return Container(
              child: ElevatedButton(
                ...,
            ));
      }

but than I got this error:

enter image description here

and I am not sure why this it happening.

I ended up giving Scaffold a key and using the GlobalKey<ScaffoldState> approach, but I really want to understand why using ScaffoldMessenger.of(context).showSnackBar() without a callback\onPressed didn't work


Solution

  • while ScaffoldMessenger.of(context) we need to give some time to be rendered properly(for full Scaffold). we can know the time from addPostFrameCallback. Also if you try to show the middle of widgets, the 1st portion will render but rest widgets will face this issue.

    here is the soulution on build method.

      WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
          _showToast(context);
        });
    
    

    to understand the concept properly we can do something like this.

    Scaffold(
          body: Container(
            height: 100,
            color: Colors.cyanAccent,
            child: Column(
              children: [
                Text("This text will render "),
                Builder(builder: (context) {
                  _showToast(context);
    
                  ///but you will be able to see Message
                  return Text("it will cause error");
                }),
                Text("This text will not render "),
              ],
            ),
          ),
        );