I got an error when learning bloc in flutter
Error is Error: Could not find the correct Provider above this Practice4HomePage 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 Practice4HomePage 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>()), } ), }
CodePudding user response:
You have to provide the bloc to your Practice4HomePage
class. One way is to provide the bloc to entire widget tree i.e. wrapping MaterialApp
with BlocProvider
or MultiBlocProvider
. Another way is to wrap BlocProvider
where you are calling Practice4HomePage
. So let's suppose you are navigating from ABC page to Practice4HomePage
, you can wrap BlocProvider
inside your navigation statement.
Example:
Navigator.of(context).push(
MaterialPageRoute<HomeForm>(
builder: (context) => BlocProvider<TimerState>(
create: (context) => TimerState(),
child: Practice4HomePage(),
),
),
),
),
CodePudding user response:
Firstly, you need to use BlocProvider instead of Provider, and secondly, wrap your child widget with Builder because BlocProvider.of(context) (or in this case context.watch()) looks from current context up the tree to find your BlocProvider, and you use same context that you provided your Bloc with, so it can't find it up the tree because it's on the same level (same context), so just use suggestion that was provided by your error, or like this:
Widget build(BuildContext context) {
return BlocProvider<Example>(
create: (_) => Example(),
child: Builder(builder: (context) => Text(context.watch<Example>())),
),
}
Or you can extract Text widget into a new StatelessWidget and that will also work because it will have it's own (new) BuildContext, like so:
class ParentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<Example>(
create: (_) => Example(),
child: ChildWidget(),
),
}
}
class ChildWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(context.watch<Example>());
}
}