I am building an application focusing on reminders. From the list of reminders present on the homepage, a reminderSection
widget is shown. The reminderSection
has an attribute thisReminder
. I want thisReminder
to be accessible to all of the descendant widgets of thisReminder
. So that they can use thisReminder
and I don’t have to pass it around.
What I’ve done is use Riverpod
. I wrapped myApp
with ProviderScope
and defined the provider in the initState
of reminderSection
like this:
final thisReminderProvider = Provider<Reminder>((ref) => widget.thisReminder);
And I want to use it in another widget, for example, reminderFormSection
which is just where the title and dateTime of the reminder is set. I did the necessary changes to the class definition and tried accessing the provider in the initState
like this:
class ReminderFormSection extends ConsumerStatefulWidget {
const ReminderFormSection({
super.key,
});
@override
ConsumerState<ReminderFormSection> createState() => _ReminderFormSectionState();
}
class _ReminderFormSectionState extends ConsumerState<ReminderFormSection> {
late Reminder thisReminder;
@override
void initState() {
thisReminder = ref.read(thisReminderProvider);
super.initState();
}
}
The problem is that I’m getting the error that thisReminderProvider
is undefined
. I think I need to define the provider outside the class and the reminderSection
file’s path to the reminderFormSection
file. But how do I define the provider outside the class if the object I want to provide is a class attribute?
3
Answers
Declare your provider outside of your ReminderForm or ReminderFormState section
if you have a ConsumerStatefulWidget
It seems what you are looking for it to be able to change the reminder that is selected from one part of your code, and be able to get the current value in another widget (
ReminderFormSection
).Providers shall always be global variables. In your case, since you want to be able to change the state you shall use a "Notifier":
Wherever you are selecting the reminder, use the notifier of the provider:
Then, in widgets where you want to access to the currently selected reminder, you shall watch the provided value.
Seems the issue lies with defining the provider within initState of reminderSection. Providers in Riverpod should be defined outside of widgets and accessed throughout the widget tree. Here’s how to achieve this and make thisReminder accessible to all descendants:
Create a separate file (e.g., reminder_providers.dart) to house your providers.
Define thisReminderProvider as a global final variable:
Instead of using a provider within reminderSection, modify it to receive thisReminder as an argument in its constructor:
Wrap your MyApp with ProviderScope.
In the build method of MyApp, provide thisReminder using Provider.value:
Now, inside reminderFormSection, you can directly access thisReminder via the Consumer widget and the ref.watch method: