Flutter could not find the correct Provider<Bloc> after navigating to different route

2,314

I found the reason for why my BlocBuilder couldn't find the CreateDidBloc after navigating. That error occurs because navigating in Flutter pushes your page right below the MaterialApp in the widget tree. That means that my newly navigated Page is above the BlocProvider which is specified in the widget tree below the MaterialApp.
To fix this I just wrapped my MaterialApp with a MultiBlocProvider and the RepositoryProvider so that the Bloc is provided globally no matter in what route I am.
This is the important extract in which I can define the blocs globally:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RepositoryProvider(
        create: (context) => CreateDidRepository(),
        child: MultiBlocProvider(
            providers: [
              BlocProvider<LanguageBloc>(
                  create: (context) =>
                      LanguageBloc(LanguagePreference.getLanguage())),
              BlocProvider<CreateDidBloc>(
                  create: (context) =>
                      CreateDidBloc(repo: context.read<CreateDidRepository>()))
            ],
            child: BlocBuilder<LanguageBloc, LanguageState>(
              builder: (context, state) {
                return MaterialApp(...)
Share:
2,314
JonasLevin
Author by

JonasLevin

Updated on December 29, 2022

Comments

  • JonasLevin
    JonasLevin over 1 year

    I'm using bloc to handle the state of a signup form. But I get the error: Error: Could not find the correct Provider<CreateDidBloc> above this BlocBuilder<CreateDidBloc, CreateDidState> Widget.
    As you can see in the error I do use the bloc CreateDidBloc and the state CreateDidState and get them through a BlocBuilder.
    The BlocBuilder is positioned in my "signup" page, which in my case is called Creation. The error occurs when I'm navigating from my introduction page to the creation page.
    Below is an extract of my MaterialApp in which I wrap the creation page with a RepositoryProvider and BlocProvider so that the creation page has access to the Bloc and repository. But for some reason does the creation page not find the BlocProvider for the CreateDidBloc after navigating to the creation page.

    initialRoute: "/introduction",
    routes: {
      "/introduction": (context) => Introduction(),
      "/create": (context) => RepositoryProvider(
            create: (context) => CreateDidRepository(),
            child: BlocProvider(
              create: (BuildContext context) => CreateDidBloc(
                repo: context.read<CreateDidRepository>(),
              ),
              child: Creation(),
            ),
          ),
    },
    

    This is how I navigate to the Creation screen:

    Navigator.push(context,
        PageTransition(type: PageTransitionType.fade, child: Creation()));
    

    Creation (signup) page:

    @override
    Widget build(BuildContext context) {
      return SafeArea(
          child: Scaffold(
              body: Column(
        children: [
          Expanded(
            child: PageView(
              physics: const NeverScrollableScrollPhysics(),
              controller: _pageController,
              onPageChanged: (index) {
                setState(() => currentStep = index);
              },
              children: [
                Step1(),
                Step2(),
                Step3(),
              ],
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              BlocBuilder<CreateDidBloc, CreateDidState>(
                builder: (context, state) {
                  return ElevatedButton(
                      onPressed: () {
                        next();
                      },
                      child: Text(L.of(context).next));
                },
              ),
              BlocBuilder<CreateDidBloc, CreateDidState>(
                builder: (context, state) {
                  return OutlinedButton(
                      onPressed:
                          state.formStatus is FormSubmitting ? null : cancel,
                      child: Text(L.of(context).back));
                },
              )
            ],
          ),
          const SizedBox(
            height: 16,
          )
        ],
      )));
    }
    

    This is the stack trace:

    When the exception was thrown, this was the stack
    #0      Provider._inheritedElementOf
    #1      Provider.of
    #2      ReadContext.read
    #3      _BlocBuilderBaseState.initState
    #4      StatefulElement._firstBuild
    
  • Dean Villamia
    Dean Villamia over 2 years
    I feel like this is supposed to be in a documentation somewhere.. Anyways thanks for the HUGE help!!!