I’m new to flutter and in need of help with this project I’m working on.
I’m trying to change the content of the body
property of the Scaffold
widget dynamically based on what the user clicked on the bottomNavigationBar
.
I am trying to use the Provider state management ’cause I’m trying to learn while I’m creating some apps.
Here’s what I got;
main.dart
void main() {
runApp(Pananta());
}
class Pananta extends StatefulWidget {
Pananta({Key? key}) : super(key: key);
@override
State<Pananta> createState() => _PanantaState();
}
class _PanantaState extends State<Pananta> {
int pageIndex = 0;
void changePage() {
setState(() {
Provider.of<ScreenData>(context).pageIndex;
});
}
@override
Widget build(BuildContext context) {
int screenDataIndex = Provider.of<ScreenData>(context).selectedIndex;
return ChangeNotifierProvider<ScreenData>(
create: (_) => ScreenData(),
builder: (context, child) =>
ScreenData.pages[context.watch<ScreenData>().selectedIndex],
child: MaterialApp(
theme: ThemeData(fontFamily: 'Poppins'),
home: SafeArea(
child: Scaffold(
body: screenDataIndex == 0
? ScreenData.pages[0]
: ScreenData.pages[screenDataIndex],
bottomNavigationBar: BottomBarMenu(),
),
),
),
);
}
}
screen_data.dart
class ScreenData extends ChangeNotifier {
int pageIndex = 0;
static List<Widget> pages = [
const HomePage(),
UserProfile(),
];
set selectedpage(int selected) {
pageIndex = selected;
}
int get selectedIndex {
notifyListeners();
return pageIndex;
}
}
The error that I’m getting:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following ProviderNotFoundException was thrown building Pananta(dirty, state:
_PanantaState#683a3):
Error: Could not find the correct Provider<ScreenData> above this Pananta 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 Pananta is under your MultiProvider/Provider<ScreenData>.
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>().toString()),
);
}`
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, child) {
// No longer throws
return Text(context.watch<Example>().toString());
}
);
}`
I think the int screenDataIndex = Provider.of<ScreenData>(context).selectedIndex;
line is what’s causing the issue, because when I remove it and set the body
to ScreenData.pages[0]
the error goes away — I can’t figure out what to do with it. Any help or articles that I can read will be very much appreciated. Thank you!
2
Answers
try a configuration like this:
Create a list of widget and put inside screens you want show.Create relatives BottomNavigationBarItem and the onTap function which update index with selectedIndex.
I think your code is harder than necessary. Try and let me know. Nice coding!
I will suggest separating the context to read the provider, and using
Consumer
widget inside widget tree.