I have the following stateless widget. I'm trying to access the SettingsCubit
in the SettingsOverlay
class using BlocProvider.of<SettingsCubit>(context).updateSettings(newSettings);
but it throws a ProviderNotFoundException.
Also tried using a MaterialPageRoute instead of a modal, but it had the same problem.
The MovieBloc
works correctly inside the MovieList
widget with a BlocBuilder
, and refreshes as it should.
Am I right, that it has something to do with that the MovieList
is in the same widget tree as the BlocProvider, and the modal/new page is a different (sub)tree? If so, shouldn't the BlocProvider.value
pass the data over to the SettingsOverlay
?
Here is the widget's full code:
class MovieScreen extends StatelessWidget {
const MovieScreen({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<SettingsCubit>(
create: (_) => SettingsCubit(),
),
BlocProvider<MovieBloc>(
create: (_) =>
MovieBloc(httpClient: http.Client())..add(MovieFetched()),
)
],
child: Scaffold(
appBar: AppBar(
title: const Text('Movies'),
actions: [
IconButton(
onPressed: () => {
showModalBottomSheet(
useSafeArea: true,
context: context,
builder: (_) {
return BlocProvider.value(
value: context.read<SettingsCubit>(),
child: const SettingsOverlay(),
);
},
),
},
icon: const Icon(Icons.add),
),
],
),
body: const MovieList(),
),
);
}
}
class SettingsOverlay extends StatelessWidget {
const SettingsOverlay({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Settings")),
body: Column(
children: [
ElevatedButton(
onPressed: () {
print("save");
BlocProvider.of<SettingsCubit>(context)
.updateSettings(Settings());
},
child: const Text("Save"),
),
],
),
);
}
}
The issue is reading SettingsCubit
on the same context where you've just created. context.read
will look up the widget tree (not current one).
You can add another builder for separate context.
Builder(builder: (context) {
return IconButton(
onPressed: () {
showModalBottomSheet(
useSafeArea: true,
context: context,
builder: (_) {
return BlocProvider.value(
value: context.read<SettingsCubit>(),
child: const SettingsOverlay(),
);
},
);
},
icon: const Icon(Icons.add),
);
}),