Flutter Error: Could not find the correct Provider<User> above this Wrapper Widget

Viewed 353

After updating/converting a program to null-safety, i'm presented with the following error:


Error: Could not find the correct Provider above this Wrapper Widget

This happens because you used a BuildContext that does not include the provider of your choice. There are a few common scenarios:

  • You added a new provider in your main.dart and performed a hot-reload. To fix, perform a hot-restart.

  • The provider you are trying to read is in a different route.

    Providers are "scoped". So if you insert of provider inside a route, then other routes will not be able to access that provider.

  • You used a BuildContext that is an ancestor of the provider you are trying to read.

    Make sure that Wrapper is under your MultiProvider/Provider. This usually happens when you are creating a provider and trying to read it immediately.

    For example, instead of:

    Widget build(BuildContext context) {
      return Provider<Example>(
        create: (_) => Example(),
        // Will throw a ProviderNotFoundError, because `context` is associated
        // to the widget that is the parent of `Provider<Example>`
        child: Text(context.watch<Example>()),
      ),
    }
    

    consider using builder like so:

    Widget build(BuildContext context) {
      return Provider<Example>(
        create: (_) => Example(),
        // we use `builder` to obtain a new `BuildContext` that has access to the provider
        builder: (context) {
          // No longer throws
          return Text(context.watch<Example>()),
        }
      ),
    }
    

If none of these solutions work, consider asking for help on StackOverflow: https://stackoverflow.com/questions/tagged/flutter


The error also points to the "relevant error-causing widget" for me it was my call to my Wrapper(), Highlighted below:

The relevant error-causing widget was: 
  Wrapper Wrapper:file:///home/AlphaUser/AndroidStudioProjects/test/lib/main.dart:78:20

The stack had more lines I didn't think were relevant. (I can add if needed)

Current Code in use:

Main.dart:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:test/screens/authenticate/test_forgot.dart';
import 'package:test/screens/authenticate/test_login.dart';
import 'package:test/screens/authenticate/test_signup.dart';
import 'package:test/screens/faq_screen.dart';
import 'package:test/screens/review_purchase_screen.dart';
import 'package:test/screens/purchased_products_screen.dart';
import 'package:test/screens/search_products_screen.dart';
import 'package:test/screens/test_postImage.dart';
import 'package:test/wrapper/wrapper.dart';
import "package:provider/provider.dart";
import 'package:test/services/auth.dart';
import 'models/user.dart';
import 'package:test/screens/product_detail_screen.dart';
import 'package:test/providers/products_provider.dart';
import 'package:test/providers/shippments_provider.dart';
import 'package:test/providers/orders.dart';
import 'package:test/screens/user_products_screen.dart';
import 'package:test/screens/edit_product_screen.dart';
import 'package:test/screens/product_checkout_screen.dart';
import 'package:test/screens/test_feed.dart';
import 'package:test/screens/profile_screen.dart';
import 'package:test/home/home.dart';
import 'package:test/home/homeUser.dart';
import 'package:flutter_stripe/flutter_stripe.dart';

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 FirebaseApp app = await Firebase.initializeApp();
 SystemChrome.setPreferredOrientations(
     [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
 Stripe.publishableKey =
     'stripe_publishableKey';
 await Stripe.instance.applySettings();
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 // This widget is the root of your application.

 @override
 Widget build(BuildContext context) {
   return MultiProvider(
     providers: [
       ChangeNotifierProvider(
         create: (ctx) => Shippments(),
       ),
       ChangeNotifierProvider(
         create: (ctx) => Orders(),
       ),
       ChangeNotifierProvider(
         create: (ctx) => Products(),
       ),
     ],
   
     child: StreamProvider<User>.value(
       
       value: AuthService().user,
       initialData: null,
       child: new MaterialApp(
         title: 'Test',
      

         theme: ThemeData(
           primarySwatch: Colors.grey,
           //   accentColor: Colors.green,
         ),

         debugShowCheckedModeBanner: false,
         //* Login Options **//
         home: Wrapper(), //***<-- Error points to this line.***
         //home: Home(),  //<-- **Works Fine if I use this instead of Wrapper().** //
         //* Login Options **//
         routes: {
           TestLogin.id: (context) => TestLogin(),
           TestSignup.id: (context) => TestSignup(),
           TestForgot.id: (context) => TestForgot(),
           ProductDetailScreen.routeName: (context) => ProductDetailScreen(),
           UserProductsScreen.routeName: (context) => UserProductsScreen(),
           EditProductScreen.routeName: (context) => EditProductScreen(),
           TestPostImageScreen.routeName: (context) => TestPostImageScreen(),
           ProductCheckoutScreen.routeName: (context) =>
               ProductCheckoutScreen(),
           PurchasedProductsScreen.routeName: (context) =>
               PurchasedProductsScreen(),
           SearchProductsScreen.routeName: (context) => SearchProductsScreen(),
           TestFeed.routeName: (context) => TestFeed(),
           ReviewPurchaseScreen.routeName: (context) => ReviewPurchaseScreen(),
           ProfileScreen.routeName: (context) => ProfileScreen(),
           FAQScreen.routeName: (context) => FAQScreen()
         },
       ),
     ),
   );
 }
}

wrapper.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test/home/home.dart';
import 'package:test/home/homeUser.dart';
import 'package:test/models/user.dart' as model;

import '../screens/authenticate/test_login.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_spinkit/flutter_spinkit.dart';

class Wrapper extends StatefulWidget {
  @override
  _WrapperState createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
  get lists => null;
  bool currentAdmin;
  bool loading = false;


  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);


    return FutureBuilder(
      future: _checkUser(user),
      builder: (context, snapshot) {
        String profile = snapshot.data;
        print("profile!!!: $profile");
        if (profile == 'true') {
          print("Snapshot has data: ${snapshot.data}");
          return Home();
        } else if (profile == 'false') {
          print("Snapshot has no data: ${snapshot.data}");
          return HomeUser();
        } else if (user == null) {
          return TestLogin();
        } else {
          //return CircularProgressIndicator();
          return SpinKitFadingCube(
            color: Colors.black,
            size: 25.0,
          );
        }
        //return null;
      },
    );
  }

  _checkUser(User user) async {
     ...
  } //_checkUser()

}

User.dart

class User {
  final String uid;

  User({this.uid});
}

Just want to add that if I replace Wrapper() with Home() the program works, but that will bypass my "user login/register/forgot password" functionality.

Any help or guidance will be much appreciated.

1 Answers

you are using the User Provider and didn't create the user provider yet

add the User Provider in the MultiProvider in main

return MultiProvider(
 providers: [
   ChangeNotifierProvider(
     create: (ctx) => Shippments(),
   ),
   ChangeNotifierProvider(
     create: (ctx) => Orders(),
   ),
   ChangeNotifierProvider(
     create: (ctx) => Products(),
   ),
   ChangeNotifierProvider( // add this
     create: (ctx) => User(),
   ),
 ],

 child: StreamProvider<User>.value(
Related