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
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(...)