SnackBars managed by the ScaffoldMessenger
Summary
#
                  The SnackBar API within the Scaffold is now handled by the
                  ScaffoldMessenger, one of which is
                  available by default within the context of a MaterialApp.
                
Context
#
                  Prior to this change, SnackBars would be shown by calling
                  on the Scaffold within the current BuildContext.
                  By calling Scaffold.of(context).showSnackBar,
                  the current Scaffold would animate a SnackBar into view.
                  This would only apply to the current Scaffold,
                  and would not persist across routes if they were changed
                  in the course of the SnackBars presentation.
                  This would also lead to errors if showSnackBar
                  would be called in the course of executing an
                  asynchronous event, and the BuildContext became invalidated
                  by the route changing and the Scaffold being disposed of.
                
                  The ScaffoldMessenger now handles SnackBars in order to
                  persist across routes and always be displayed on the current Scaffold.
                  By default, a root ScaffoldMessenger is included in the MaterialApp,
                  but you can create your own controlled scope for the ScaffoldMessenger
                  
                  to further control which Scaffolds receive your SnackBars.
                
Description of change
#The previous approach called upon the Scaffold to show a SnackBar.
Scaffold(
  key: scaffoldKey,
  body: Builder(
    builder: (BuildContext context) {
      return GestureDetector(
        onTap: () {
          Scaffold.of(context).showSnackBar(SnackBar(
            content: const Text('snack'),
            duration: const Duration(seconds: 1),
            action: SnackBarAction(
              label: 'ACTION',
              onPressed: () { },
            ),
          ));
        },
        child: const Text('SHOW SNACK'),
      );
    },
  )
);
                    
                    
                    
                  
                  The new approach calls on the ScaffoldMessenger to show
                  the SnackBar. In this case, the Builder is no longer
                  required to provide a new scope with a BuildContext that
                  is "under" the Scaffold.
                
Scaffold(
  key: scaffoldKey,
  body: GestureDetector(
    onTap: () {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: const Text('snack'),
        duration: const Duration(seconds: 1),
        action: SnackBarAction(
          label: 'ACTION',
          onPressed: () { },
        ),
      ));
    },
    child: const Text('SHOW SNACK'),
  ),
);
                    
                    
                    
                  
                  When presenting a SnackBar during a transition,
                  the SnackBar completes a Hero animation,
                  moving smoothly to the next page.
                
                  The ScaffoldMessenger creates a scope in which all descendant
                  Scaffolds register to receive SnackBars,
                  which is how they persist across these transitions.
                  When using the root ScaffoldMessenger provided by the
                  MaterialApp, all descendant Scaffolds receive SnackBars,
                  unless a new ScaffoldMessenger scope is created further down the tree.
                  By instantiating your own ScaffoldMessenger,
                  you can control which Scaffolds receive SnackBars, and which are not,
                  based on the context of your application.
                
                  The method debugCheckHasScaffoldMessenger is available to assert
                  that a given context has a ScaffoldMessenger ancestor.
                  Trying to present  a SnackBar without a ScaffoldMessenger
                   ancestor
                  present results in an assertion such as the following:
                
No ScaffoldMessenger widget found.
Scaffold widgets require a ScaffoldMessenger widget ancestor.
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp
at the top of your application widget tree.
                    
                    
                    
                  Migration guide
#Code before migration:
// The ScaffoldState of the current context was used for managing SnackBars.
Scaffold.of(context).showSnackBar(mySnackBar);
Scaffold.of(context).hideCurrentSnackBar(mySnackBar);
Scaffold.of(context).removeCurrentSnackBar(mySnackBar);
// If a Scaffold.key is specified, the ScaffoldState can be directly
// accessed without first obtaining it from a BuildContext via
// Scaffold.of. From the key, use the GlobalKey.currentState
// getter. This was previously used to manage SnackBars.
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Scaffold(
  key: scaffoldKey,
  body: ...,
);
scaffoldKey.currentState.showSnackBar(mySnackBar);
scaffoldKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldKey.currentState.removeCurrentSnackBar(mySnackBar);
                    
                    
                    
                  Code after migration:
// The ScaffoldMessengerState of the current context is used for managing SnackBars.
ScaffoldMessenger.of(context).showSnackBar(mySnackBar);
ScaffoldMessenger.of(context).hideCurrentSnackBar(mySnackBar);
ScaffoldMessenger.of(context).removeCurrentSnackBar(mySnackBar);
// If a ScaffoldMessenger.key is specified, the ScaffoldMessengerState can be directly
// accessed without first obtaining it from a BuildContext via
// ScaffoldMessenger.of. From the key, use the GlobalKey.currentState
// getter. This is used to manage SnackBars.
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
ScaffoldMessenger(
  key: scaffoldMessengerKey,
  child: ...
)
scaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
// The root ScaffoldMessenger can also be accessed by providing a key to
// MaterialApp.scaffoldMessengerKey. This way, the ScaffoldMessengerState can be directly accessed
// without first obtaining it from a BuildContext via ScaffoldMessenger.of. From the key, use
// the GlobalKey.currentState getter.
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
  scaffoldMessengerKey: rootScaffoldMessengerKey,
  home: ...
)
rootScaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
                    
                    
                    
                  Timeline
#
                  Landed in version: 1.23.0-13.0.pre
                  In stable release: 2.0.0
                
References
#API documentation:
Relevant issues:
Relevant PRs:
Unless stated otherwise, the documentation on this site reflects Flutter 3.35.5. Page last updated on 2025-10-30. View source or report an issue.