Unhandled Exception: No ScaffoldMessenger widget found

Issue

My question is about dart language

I got these errors on terminal:

E/flutter ( 8346): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)]
Unhandled Exception: No ScaffoldMessenger widget found. E/flutter (
8346): MyApp widgets require a ScaffoldMessenger widget ancestor.
E/flutter ( 8346): The specific widget that could not find a
ScaffoldMessenger ancestor was: E/flutter ( 8346): MyApp E/flutter (
8346): The ancestors of this widget were: E/flutter ( 8346):
_InheritedProviderScope<UserProvider?> E/flutter ( 8346): ChangeNotifierProvider E/flutter ( 8346): _NestedHook
E/flutter ( 8346): MultiProvider E/flutter ( 8346): [root]

This is my code:

**main.dart**

import 'package:amazon_clone/common/bottom_bar.dart';
import 'package:amazon_clone/constants/global_variables.dart';
import 'package:amazon_clone/features/screens/auth_screen.dart';
import 'package:amazon_clone/features/services/auth_service.dart';
import 'package:amazon_clone/providers/user_provider.dart';
import 'package:amazon_clone/router.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MultiProvider(providers: [
    ChangeNotifierProvider(
        create: (context) => UserProvider()
    ),
  ],
  child: const MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final AuthService authService = AuthService();

  @override
  void initState() {
    super.initState();
    authService.getUserData(context);
  }
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Amazon clone',
      theme: ThemeData(
        scaffoldBackgroundColor: GlobalVariables.backgroundColor,
        colorScheme: ColorScheme.light(
          primary: GlobalVariables.secondaryColor,
        ),
        appBarTheme: const AppBarTheme(
          elevation: 0,
          iconTheme: IconThemeData(color: Color(0xff3B3B3B))
        )
      ),
      onGenerateRoute: (settings) => generateRoute(settings),
      home: Provider.of<UserProvider>
        (context).user.token.isNotEmpty
          ? const BottomBar()
          : const AuthScreen(),
    );
  }
}

bottom_bar.dart

import 'package:amazon_clone/features/account/screens/account_screen.dart';
import 'package:amazon_clone/home/screens/home_screens.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class BottomBar extends StatefulWidget {
  static const String routeName = '/actual-home';
  const BottomBar({Key? key}) : super(key: key);

  @override
  State<BottomBar> createState() => _BottomBarState();
}

class _BottomBarState extends State<BottomBar> {
  int _page = 0;
  double bottomBarWidth = 42;
  double bottomBarBorderWidth = 5;

  List<Widget> pages = [
    const HomeScreen(),
    const AccountScreen(),
    const Center(
      child: Text('Cart Page'),),
  ];

  void updatePage(int page) {
    setState(() {
      _page = page;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: pages[_page],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _page,
        selectedItemColor:  Color(0xff003f7d),
        unselectedItemColor:   Color(0xff4669ad),
        backgroundColor: Color(0xffeeeeee),
        iconSize: 28,
        onTap: updatePage,
        items: [
          BottomNavigationBarItem(icon: Container(
            width: bottomBarWidth,
            decoration: BoxDecoration(
              border: Border(top: BorderSide(
                color: _page == 0
                    ? Color(0xff4669ad)
                    : Color(0xffeeeeee),
                width: bottomBarBorderWidth,
              ),
              ),
            ),
            child: const Icon(Icons.home_outlined),
          ),
            label: '',
          ),
          BottomNavigationBarItem(icon: Container(
            width: bottomBarWidth,
            decoration: BoxDecoration(
              border: Border(top: BorderSide(
                color: _page == 1
                    ? Color(0xff4669ad)
                    : Color(0xffeeeeee),
                width: bottomBarBorderWidth,
              ),
              ),
            ),
            child: const Icon(
                Icons.person_outline_outlined),
          ),
            label: '',
          ),
          BottomNavigationBarItem(icon: Container(
            width: bottomBarWidth,
            decoration: BoxDecoration(
              border: Border(top: BorderSide(
                color: _page == 2
                    ? Color(0xff4669ad)
                    : Color(0xffeeeeee),
                width: bottomBarBorderWidth,
              ),
              ),
            ),
            child: Badge(
              elevation: 0,
              badgeContent: const Text('2'),
              badgeColor: Colors.white,
              child: const Icon(
                  Icons.shopping_cart_outlined),
            ),
          ),
            label: '',
          ),
        ],
      ),
    );
  }
}

auth_screen.dart

import 'package:amazon_clone/common/widgets/custom_button.dart';
import 'package:amazon_clone/common/widgets/custom_textfield.dart';
import 'package:amazon_clone/constants/global_variables.dart';
import 'package:amazon_clone/features/services/auth_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum Auth {
  signin,
  signup,
}

class AuthScreen extends StatefulWidget {
  static const String routeName = '/auth-screen';
  const AuthScreen({Key? key}) : super(key: key);

  @override
  State<AuthScreen> createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
  Auth _auth = Auth.signup;
  final _signUpFormKey = GlobalKey<FormState>();
  final _signInFormKey = GlobalKey<FormState>();
  final AuthService authService = AuthService();
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  final TextEditingController _nameController = TextEditingController();


  @override
  void dispose() {
    super.dispose();
    _emailController.dispose();
    _passwordController.dispose();
    _nameController.dispose();
  }
  void signUpUser() {
    authService.signUpUser(
        context: context,
        email: _emailController.text,
        password: _passwordController.text,
        name: _nameController.text
    );
  }
  void signInUser() {
    authService.signInUser(
        context: context,
        email: _emailController.text,
        password: _passwordController.text,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: GlobalVariables.backgroundColor,
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'Welcome',
                style: TextStyle(
                  fontSize: 22,
                  fontWeight: FontWeight.w500,
                ),
                ),
                ListTile(
                  tileColor: _auth == Auth.signup
                  ? GlobalVariables.backgroundColor
                  : GlobalVariables.greyBackgroundCOlor,
                  title: const Text(
                    'Create account',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  leading: Radio(
                    activeColor: GlobalVariables.secondaryColor,
                    value: Auth.signup,
                    groupValue: _auth,
                    onChanged: (Auth? val) {
                      setState(() {
                        _auth = val!;
                      });
                    },
                  ),
                ),
                if(_auth == Auth.signup)
                  Container(
                    padding: const EdgeInsets.all(8.0),
                    color: GlobalVariables.backgroundColor,
                    child: Form(
                      key: _signUpFormKey,
                      child: Column(
                        children: [
                          CustomTextField(
                            controller: _nameController,
                            hintText: 'Name',),
                          SizedBox(height: 10,),
                          CustomTextField(
                            controller: _emailController,
                            hintText: 'Email',),
                          SizedBox(height: 10,),
                          CustomTextField(
                            controller: _passwordController,
                            hintText: 'Password',
                          ),
                          const SizedBox(height: 10,),
                          CustomButton(
                              text: 'Sign Up',
                              onTap: () {
                                if(_signUpFormKey.currentState!.validate()){
                                  signUpUser();
                                };
                              },)
                        ],
                      ),
                    ),
                  ),
                ListTile(
                  tileColor: _auth == Auth.signin
                      ? GlobalVariables.backgroundColor
                      : GlobalVariables.greyBackgroundCOlor,
                  title: const Text(
                    'Sing-In',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  leading: Radio(
                    activeColor: GlobalVariables.secondaryColor,
                    value: Auth.signin,
                    groupValue: _auth,
                    onChanged: (Auth? val) {
                      setState(() {
                        _auth = val!;
                      });
                    },
                  ),
                ),
                if(_auth == Auth.signin)
                Container(
                  padding: const EdgeInsets.all(8.0),
                  color: GlobalVariables.backgroundColor,
                  child: Form(
                    key: _signInFormKey,
                    child: Column(
                      children: [
                        CustomTextField(
                          controller: _emailController,
                          hintText: 'Email',),
                        SizedBox(height: 10,),
                        CustomTextField(
                          controller: _passwordController,
                          hintText: 'Password',
                        ),
                        const SizedBox(height: 10,),
                        CustomButton(
                          text: 'Sign In',
                         onTap: () {
                           if(_signInFormKey.currentState!.validate()){
                             signInUser();
                           };
                          },)
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

utils.dart

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';

void showSnackBar(BuildContext context, String text) {   ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Text(text),
    ),   ); }

auth_service.dart

class AuthService {
      void signUpUser({
        required BuildContext context,
        required String email,
        required String password,
        required String name,
    }) async {
        try {
          User user = User(
              id: '',
              name: name,
              password: password,
              email: email,
              address: '',
              type: '',
              token: '',
          );
    
          http.Response res = await http.post(
              Uri.parse('$uri/api/signup'),
              body: user.toJson(),
              headers: <String, String>{
                'Content-Type': 'application/json; charset=UTF-8',
              },
          );
          httpErrorHandle(
              response: res,
              context: context,
              onSuccess: () {
                showSnackBar(
                    context,
                    'Account created! Login with the same credential');
              },
          );
        } catch (e) {
          showSnackBar(context, e.toString());
        }
      }
      //sign up user
      void signInUser({
        required BuildContext context,
        required String email,
        required String password,
      }) async {
        try {
    
          http.Response res = await http.post(
            Uri.parse('$uri/api/signin'),
            body: jsonEncode({
              'email': email,
              'password': password,
            }),
            headers: <String, String>{
              'Content-Type': 'application/json; charset=UTF-8',
            },
          );
          httpErrorHandle(
            response: res,
            context: context,
            onSuccess: () async {
              SharedPreferences prefs = await SharedPreferences.getInstance();
              Provider.of<UserProvider>(context, listen: false).setUser(res.body);
              await prefs.setString('x-auth-token', jsonDecode(res.body)['token']);
              Navigator.pushNamedAndRemoveUntil(
                  context,
                  BottomBar.routeName,
                      (route) => false,
              );
            },
          );
        } catch (e) {
          showSnackBar(context, e.toString());
        }
      }
    
      //get user data
      void getUserData(
          BuildContext context,
      ) async {
        try {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          String? token = prefs.getString('x-auth-token');
    
          if(token == null) {
            prefs.setString('x-auth-token', '');
          }
          var tokenRes = await http.post(
              Uri.parse('$uri/tokenIsValid'),
            headers: <String, String> {
                'Content-Type':'application/json; charset=UTF-8',
              'x-auth-token': token!
            },
          );
          var response = jsonDecode(tokenRes.body);
    
          if(response == true) {
            http.Response userRes = await http.get(
              Uri.parse('$uri/'),
              headers: <String, String> {
                'Content-Type':'application/json; charset=UTF-8',
                'x-auth-token': token
              },
            );
            var userProvider = Provider.of<UserProvider>(context, listen: false);
            userProvider.setUser(userRes.body);
            //get user data
          }
        } catch (e) {
          showSnackBar(context, e.toString());
        }
      }

Can you please help me in order to solve this issue

Thank you in advance

Solution

The problem is with the authService.getUserData(context);. The context passed to it doesn’t have a MaterialApp as its parent to be used by the SnackBar in case of an error, hence the exception being thrown.

I’d recommend using a Builder with a FutureBuilder to get the context inside the MaterialApp like the following:

home: Builder(builder: (context) {
  return FutureBuilder(
    future: authService.getUserData(context),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {
        return Provider.of<UserProvider>(context).user.token.isNotEmpty
            ? const BottomBar()
            : const AuthScreen();
      }
      return const Center(child: CircularProgressIndicator());
    },
  );
}),

Answered By – lepsch

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published