Error related to Flutter provider package
Solution 1
Because you have to declare the provider class above the class were your using it , if u find this ans crt mark it as crt
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (ctx) => MyUser(),),
],
child: MaterialApp());
Solution 2
You have to warp the parent class with the provider class you are using inside. For doing so the easiest way is to add a static method in widget havingMaterialPageRoute
which helps to navigate to SettingsForm
screen.
class SettingsForm extends StatefulWidget {
static Widget getWidget() {
return new Provider(
create: (_) => MyUser(),
child: ChangeNotifierProvider(
create: (BuildContext context) => MyUser(),
builder: (_,_) => SettingsForm()
),
);
}
@override
_SettingsFormState createState() => _SettingsFormState();
}
To open SettingsForm
screen just call getRoute
function on button pressed. Check the below code.
Open SettingsForm screen from Home screen
void _showSettingsPanel() {
showModalBottomSheet(context: context, builder: (context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
child: SettingsForm.getWidget(), <-- Here
);
});
}
Mike Osborn
Updated on December 17, 2022Comments
-
Mike Osborn over 1 year
I am building a setting widget in my flutter app and I am getting this error :
Error: Could not find the correct Provider above this SettingsForm Widget
Update Adding whole debug snippet:
Launching lib\main.dart on AOSP on IA Emulator in debug mode... ════════ Exception caught by widgets library ═══════════════════════════════════ The following ProviderNotFoundException was thrown building SettingsForm(dirty, state: _SettingsFormState#c73b8): Error: Could not find the correct Provider<MyUser> above this SettingsForm 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 SettingsForm is under your MultiProvider/Provider<MyUser>. 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>()), } ), } ``` If none of these solutions work, consider asking for help on StackOverflow: https://stackoverflow.com/questions/tagged/flutter The relevant error-causing widget was SettingsForm When the exception was thrown, this was the stack #0 Provider._inheritedElementOf #1 Provider.of #2 _SettingsFormState.build #3 StatefulElement.build #4 ComponentElement.performRebuild ... ════════════════════════════════════════════════════════════════════════════════
i UPDATED IT AND ADDED SOME EXTRA CODE SO YOU CAN SEE BETTER
setting.dart:
class SettingsForm extends StatefulWidget { @override _SettingsFormState createState() => _SettingsFormState(); } class _SettingsFormState extends State<SettingsForm> { final _formKey = GlobalKey<FormState>(); final List<String> sugars = ['0', '1', '2', '3', '4']; final List<int> strengths = [100, 200, 300, 400, 500, 600, 700, 800, 900]; // form values String? _currentName; String? _currentSugars; int? _currentStrength; @override Widget build(BuildContext context) { MyUser user = Provider.of<MyUser>(context); return StreamBuilder<UserData>( stream: DatabaseService(uid: user.uid).userData, builder: (context, snapshot) { if (snapshot.hasData) { UserData? userData = snapshot.data; return Form( key: _formKey, child: Column( children: <Widget>[ Text( 'Update your brew settings.', style: TextStyle(fontSize: 18.0), ), SizedBox(height: 20.0), TextFormField( initialValue: userData!.name, decoration: textInputDecoration, validator: (val) => val!.isEmpty ? 'Please enter a name' : null, onChanged: (val) => setState(() => _currentName = val), ), SizedBox(height: 10.0), DropdownButtonFormField<String>( value: _currentSugars ?? userData.sugars, decoration: textInputDecoration, items: sugars.map((sugar) { return DropdownMenuItem( value: sugar, child: Text('$sugar sugars'), ); }).toList(), onChanged: (val) => setState(() => _currentSugars = val), ), SizedBox(height: 10.0), Slider( value: (_currentStrength ?? userData.strength).toDouble(), activeColor: Colors.brown[_currentStrength ?? userData.strength], inactiveColor: Colors.brown[_currentStrength ?? userData.strength], min: 100.0, max: 900.0, divisions: 8, onChanged: (val) => setState(() => _currentStrength = val.round()), ), ElevatedButton( style: ElevatedButton.styleFrom(primary: Colors.pink[400]), child: Text( 'Update', style: TextStyle(color: Colors.white), ), onPressed: () async { if (_formKey.currentState!.validate()) { await DatabaseService(uid: user.uid).updateUserData( _currentSugars ?? snapshot.data!.sugars, _currentName ?? snapshot.data!.name, _currentStrength ?? snapshot.data!.strength); Navigator.pop(context); } }), ], ), ); } else { return Loading(); } }); } }
UPDATE: I AM INCLUDING THE HOME.DART FILE THAT INCLUDES THE 'SETTINGFORM' WIDGET home.dart :
class Home extends StatelessWidget { final AuthService _auth = AuthService(); @override Widget build(BuildContext context) { void _showSettingsPanel() { showModalBottomSheet(context: context, builder: (context) { return Container( padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0), child: SettingsForm(), <-- Here ); }); } return StreamProvider<List<Brew>?>.value( value: DatabaseService(uid: '').brews, initialData: null, child: Scaffold( backgroundColor: Colors.brown[50], appBar: AppBar( title: Text('Brew Crew'), backgroundColor: Colors.brown[400], elevation: 0.0, actions: <Widget>[ TextButton.icon( icon: Icon(Icons.person), label: Text('logout'), onPressed: () async { await _auth.signOut(); }, ), TextButton.icon( icon: Icon(Icons.settings), label: Text('settings'), onPressed: () => _showSettingsPanel(), ) ], ), body: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/coffee_bg.png'), fit: BoxFit.cover, ), ), child: BrewList() ), ), ); } }
user.dart:
class MyUser { final String uid; MyUser({ required this.uid }); } class UserData { final String uid; final String name; final String sugars; final int strength; UserData({ required this.uid, required this.sugars, required this.strength, required this.name }); }
-
Midhun MP almost 3 yearsWhy did you defined that method inside the build ?
-
Mike Osborn almost 3 yearsIf you meant the provider class they are built inside widgets.
-
Midhun MP almost 3 yearsI mean that
_showSettingsPanel
method.
-
-
Mike Osborn almost 3 yearsCan you briefly explain what's causing the problem?
-
PRATHIV almost 3 yearsif your using the provider class inside the widgets then you have to declare it above that class , so it's better to declare it top of all widgets , so declare it above MaterialApp
-
Mike Osborn almost 3 yearsI am not using it in main.dart i am using it in setting_form.dart
-
Mike Osborn almost 3 yearsThnx for responding also i updated my code
-
Mike Osborn almost 3 yearsI am getting some probs recently
-
Mike Osborn almost 3 yearsUpdate i am using stream provider and the setting bar is in my home screen (home.dart) in the app
-
Mike Osborn almost 3 years@Alphamerc getting error on change notifier provider pls see update screenshot in my q
-
TheAlphamerc almost 3 yearsDoes the
MyUser
class extend theChangeNotifier
class? -
Mike Osborn almost 3 yearsI think I have created a 'UserData' class for setting widget
-
Mike Osborn almost 3 yearsBut MyUser gives the uid class object
-
TheAlphamerc almost 3 years
MyUser
class doesn't extend theChangeNotifire
class so you can't use MyUser user = Provider.of<MyUser>(context); -
Mike Osborn almost 3 yearsI tried to put 'UserData' instead of 'MyUser' but it didn't work out
-
Mike Osborn almost 3 yearsstill haven't found the answer to this question
-
Mike Osborn almost 3 yearsI added the whole debug error can u fix it?