Home > Blockchain >  Error: Could not find the correct Provider<AuthState> above this AuthPage Widget
Error: Could not find the correct Provider<AuthState> above this AuthPage Widget

Time:02-22

ERROR: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following ProviderNotFoundException was thrown building AuthPage(dirty, state: _AuthPageState#7ac1c): Error: Could not find the correct Provider above this AuthPage 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 AuthPage 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>()),
        }
      ),
    }
    
    
    
    
    
    
    
    
    

My Code:

AuthPage.dart:-

import 'package:first_app/pages/auth/bloc/auth_state.dart';
import 'package:first_app/pages/auth/widgets/auth_button.dart';
import 'package:first_app/pages/auth/widgets/otp_page.dart';
import 'package:first_app/pages/auth/widgets/phone_page.dart';
import 'package:first_app/pages/auth/widgets/set_up_account.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';




class AuthPage extends StatefulWidget {
  final int page;
  final String? uid;
  const AuthPage({
    Key? key,
    this.page = 0,
    this.uid,
  }) : super(key: key);

  @override
  _AuthPageState createState() => _AuthPageState();
}

class _AuthPageState extends State<AuthPage> {
  @override
  Widget build(BuildContext context) {
    final state = Provider.of<AuthState>(context);
    final screenSize = MediaQuery.of(context).size;
    return 
    
    
    Builder(builder: (context) {
      return Stack(
        children: [
          Container(
            height: screenSize.height,
            width: screenSize.width,
            color: Colors.white,
            child: PageView(
              controller: state.controller,
              onPageChanged: state.onPageChanged,
              physics: NeverScrollableScrollPhysics(),
              children: [
                PhonePage(),
                OtpPage(),
                SetUpAccount(),
              ],
            ),
          ),
          AuthButton(),
        ],
      );
    });
  }
}

class AuthPageWidget extends StatelessWidget {
  final int page;
  final String? uid;

  const AuthPageWidget({
    Key? key,
    required this.page,
    this.uid,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final state = AuthState(page, uid ?? '');
    return ChangeNotifierProvider(
      create: (_) => state,
      child: ChangeNotifierProvider.value(
        value: state,
        child: AuthPage(page: page, uid: uid),
      ),
    );
  }
}

AuthState.dart

import 'dart:async';

import 'package:first_app/models/user.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/services/auth.dart';
import 'package:first_app/services/map_services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

enum PhoneAuthState { initial, success, loading, codeSent, error }


/*part of 'auth_bloc.dart';
abstract class AuthState extends Equatable {
  const AuthState();

  @override
  List<Object> get props => [];
}*/


class AuthState extends ChangeNotifier {
  final authService = AuthService.instance;
  final userRepo = UserRepository.instance;

  PhoneAuthState _phoneAuthState = PhoneAuthState.initial;

  String verificationId = '';

  TextEditingController phoneController = TextEditingController();
  TextEditingController otpController = TextEditingController();
  TextEditingController firstNameController = TextEditingController();
  TextEditingController lastNameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  TextEditingController licensePlateController = TextEditingController();
  TextEditingController vehicleColorController = TextEditingController();
  TextEditingController vehicleTypeController = TextEditingController();
  TextEditingController vehicleManufacturersController = TextEditingController();
  Roles role = Roles.passenger;

  PageController? controller;
  int pageIndex = 0;
  String uid = '';

  int timeOut = 30;

  bool get isRoleDriver => role == Roles.driver;

  AuthState(int page, String uid) {
    this.uid = uid;
    controller = PageController(initialPage: page);
    pageIndex = page;
    notifyListeners();
    siginCurrentUser();
  }

  PhoneAuthState get phoneAuthState => _phoneAuthState;

  set changeRoleState(int value) {
    role = Roles.values[value];
    notifyListeners();
  }

  set phoneAuthStateChange(PhoneAuthState phoneAuthState) {
    _phoneAuthState = phoneAuthState;
    notifyListeners();
  }

  void animateToNextPage(int page) {
    controller!.animateToPage(page, duration: Duration(milliseconds: 400), curve: Curves.easeIn);
    pageIndex = page;
    notifyListeners();
  }

  void onPageChanged(int value) {
    pageIndex = value;
    notifyListeners();
  }

  Future<void> signUp() async {
    phoneAuthStateChange = PhoneAuthState.loading;
    final address = await MapService.instance?.getCurrentPosition();
    try {
      final user = User(
        uid: uid,
        isActive: true,
        firstname: firstNameController.text,
        lastname: lastNameController.text,
        email: emailController.text,
        createdAt: DateTime.now(),
        isVerified: true,
        licensePlate: licensePlateController.text,
        phone: "234${phoneController.text}",
        vehicleType: vehicleTypeController.text,
        vehicleColor: vehicleColorController.text,
        vehicleManufacturer: vehicleManufacturersController.text,
        role: role,
        latlng: address?.latLng,
      );
      await userRepo.setUpAccount(user);
      phoneAuthStateChange = PhoneAuthState.success;
    } on FirebaseException catch (e) {
      print(e.message);
      phoneAuthStateChange = PhoneAuthState.error;
    }
  }

  Future<void> phoneNumberVerification(String phone) async {
    await AuthService.instance!.verifyPhoneSendOtp(phone, completed: (credential) async {
      if (credential.smsCode != null && credential.verificationId != null) {
        verificationId = credential.verificationId ?? '';
        notifyListeners();
        await verifyAndLogin(credential.verificationId!, credential.smsCode!, phoneController.text);
      }
    }, failed: (error) {
      phoneAuthStateChange = PhoneAuthState.error;
    }, codeSent: (String id, int? token) {
      verificationId = id;
      notifyListeners();

      phoneAuthStateChange = PhoneAuthState.codeSent;
      codeSentEvent();
      print('code sent $id');
    }, codeAutoRetrievalTimeout: (id) {
      verificationId = id;
      notifyListeners();

      phoneAuthStateChange = PhoneAuthState.codeSent;
      animateToNextPage(1);
      print('timeout $id');
    });
    animateToNextPage(1);
    notifyListeners();
  }

  Future<void> verifyAndLogin(String verificationId, String smsCode, String phone) async {
    phoneAuthStateChange = PhoneAuthState.loading;

    final uid = await authService?.verifyAndLogin(verificationId, smsCode, phone);
    await userRepo.getUser(uid);
    this.uid = uid ?? '';
    animateToNextPage(2);
    notifyListeners();
    phoneAuthStateChange = PhoneAuthState.success;
    print('completed');
  }

  Future<void> siginCurrentUser() async {
    await userRepo.signInCurrentUser();
  }

  Future<void> codeSentEvent() async {
    animateToNextPage(1);
    _startCountDown();
  }

  void _startCountDown() {
    Timer.periodic(Duration(seconds: 1), (timer) {
      if (timer.tick > 30) {
        timer.cancel();
      } else {
        --timeOut;
      }
      notifyListeners();
    });
  }
}

main.dart

import 'package:first_app/pages/home/home.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/ui/theme.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    UserRepository.instance.signInCurrentUser();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BrilliantDrive',
      theme: CityTheme.theme,
      home: HomePage(),
    );
  }
}

CodePudding user response:

Initialize your provider 1st. Refer this https://stackoverflow.com/a/68418866/16467763.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(
  MultiProvider(
   providers: [
     ChangeNotifierProvider<AuthState>(
       create: (context) => AuthState(),
     ),   
   ],
   child: MyApp(),
  ),
 );
}

CodePudding user response:

   class AuthPageWidget extends StatelessWidget {
  final int page;
  final String? uid;

  const AuthPageWidget({
    Key? key,
    required this.page,
    this.uid,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final state = AuthState(page, uid ?? '');
    return ChangeNotifierProvider(
      create: (_) => state,
          child: ChangeNotifierProvider.value(
            value: state,
            child: AuthPage(page: page, uid: uid),
          ),
        );
      }
}

You should move the ChangeNotifierProvider to your main.dart like this

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  final state = AuthState(page, uid ?? '');
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: ChangeNotifierProvider(
         create: (_) => state,
        child: AuthPage(page: page, uid: uid),
      ),
    ),
  );
}

OR

class SomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home:  ChangeNotifierProvider(
      create: (_) => state,
          child: ChangeNotifierProvider.value(
            value: state,
            child: AuthPage(page: page, uid: uid),
          ),
        )
      ),
    );
  }
}
  • Related