Reputation: 1013
I'm using Flutter Bloc
for a project.
This is the structure:
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (context) {
return BlocA()
..add(FetchEvent());
},
),
BlocProvider<BlocC>(
create: (context) {
return BlocC()..add(FetchEvent());
},
),
],
child: IndexedStack(
index: _pageNum,
children: [
ChildA(),
ChildB(),
],
),
)
Inside ChildB
I have a Navigator.push()
to a ChildC
, where BlocC
is being used (BlocConsumer
), but I'm getting an error,
Flutter could not find the correct Provider above BlocConsumer<BlocC> Widget
Edit
There is a button in ChildB
that navigates to ChildC
on pressed.
Like,
TextButton( // this code exists inside a scaffold widget
child: Text("Page C"),
onPressed: () {
Navigator.push(context, CupertinoPageRoute(builder: (context) => ChildC()));
}
),
This is the bloc consumer in ChildC
// Child C
Scaffold(
body: BlocConsumer<BlocC, CState>(
builder: (context, state) {
if(state is CSuccessState) {
return _body();
} else if (state is CLoadingState || state is CInitState) {
return Center(child: CircularProgressIndicator());
} else return Center(child: Text("Something went wrong"));
},
listener: (context, state) {},
),
);
Edit 2
I found this answer, apparently, this is an issue when using Navigator.push
. Still, if anyone knows how to solve it in my case, do let me know
Upvotes: 3
Views: 2292
Reputation: 8202
Provider is scoped.
It means only the subtree of your provider (your child widgets) can access it.
When you push a new page, it pushed it to the MaterialApp
router (default root router of your app), and your widget tree looks like:
MaterialApp
|- Provider
| |- TextButton (with onPressed: () => Navigator.push())
|- ChildC
As you can see, your ChildC
is not below the Provider
(s).
A way to solve it is to move your providers above your MaterialApp
:
Provider
|- MaterialApp
| |- TextButton (with onPressed: () => Navigator.push())
| |- ChildC
You can push your page to a nested router that is below your Provider
:
MaterialApp
|- Provider
| |- Router
| | |- TextButton (with onPressed: () => Navigator.push())
| | |- ChildC
BlockC
above ChildC
:TextButton( // this code exists inside a scaffold widget
child: Text("Page C"),
onPressed: () {
final blockCValue = context.read<BlockC>();
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => Provider<BlockC>.value(
value: blockCValue,
child: ChildC(),
),
);
},
),
Upvotes: 6
Reputation: 5049
The Navigator's behaviour is expected.
You should replace
Navigator.push(context, CupertinoPageRoute(builder: (context) => ChildC()));
with
Navigator.push(context, CupertinoPageRoute(builder: (ctx) => BlocProvider.value(value: context.read<BlocC>()), child: ChildC());
This will work.
Upvotes: 1