Why Choose Riverpod? - Riverpod Extensions

Search for a command to run...

No comments yet. Be the first to comment.
This is a series based off the topic I covered at the 2023 Devfest in Cape Town on 23 November.
This post is based off a presentation I did at Devfest 2023 in Cape Town on 23 Nov 2023. VIDEO | PRESENTATION Previously we covered the extension methods provided by Riverpod, in this post we will take look at how we access these providers UI Some...
The Problem Wasn’t Triage Most AI workflows in software engineering still keep the human directly in the middle of triage. The AI might help write code. It might explain a stack trace. It might summar

There’s been a steady undercurrent of people switching tools lately. Copilot to Claude. Claude to something else. Codex quietly entering more workflows. A lot of confidence in different directions, of

It’s been said to me that at times my responses can come across as a “no” first-unintentionally, of course, but real all the same. Not long ago, someone on my team shared an idea they were exploring. I began with a caution, meaning to help them avoid...

The opening sentence of any message often carries more weight than everything that follows. I’ve learned this the hard way. Recently, a report shared something he wanted to pursue. I was supportive — I really was — but my first response came as a cau...

One of the things I’ve always been comfortable with is admitting when I don’t know something. To me, it’s one of the real distinctions between the more and less experienced engineers — and honestly, people in general. When you’re earlier in your care...

This post is based off a presentation I did at Devfest 2023 in Cape Town on 23 Nov 2023. VIDEO | PRESENTATION
Previously we took a look at what Riverpod is, in this post we Weill take a look at the extension methods provided by Riverpod.
To help with controlling the global access to your states data, Riverpod provides 2 extension methods, namely autoDispose and family.
final counterProvider = Provider.autoDispose<int>((ref) => 0);
The autoDispose extension does very must what the name suggests, once the widget instantiating the Provider is unmounted, the Provider is removed along with all of it's data.
The family extension, which took me a while to fully understand initially, is the real powerhouse here, it serves 2 purposes, the first is simply the ability to pass data into your Provider. The one caveat with that is that it only allows a single argument to be passed in, but it does at least support all data types, so if you needed multiple pieces of information, you could make use of a data class or possible even a Map.
final messagesFamily = FutureProvider.family<Message, String>((ref, id) async {
return dio.get('http://my_api.dev/messages/$id');
});
A common, albeit simple, use case one would run into where this is handy would be when making of of the FutureProvider, one of Riverbeds providers for dealing with promises, such as network request.
As you can see above, we are passing in a String as the second argument to the provider, with the first argument being the expected response type from the API call.
A big reason to make use of the family extension is to control unique versions of a state when needing to have access to the same logic with multiple widgets in the same view.

Looking at this image you will see the 3 cards, all 3 of them make use of the same business logic, but would need to be able to uniquely track their data.
final sharedProvider = StateNotifierProvider
.family<SharedNotifier, SharedState, String>(
(ref, orderId) => OperationsNotifier(ref, orderId),
);
class SharedNotifier extends StateNotifier<SharedState> {
final Ref ref;
final String orderId;
SharedNotifier(this.ref, this.orderId) : super(SharedState.initial());
}
The above code is a simple example of how one would make use of shared logic while also maintaining unique instances and therefor data.
In order to maintain this uniqueness with the family extension, we need to ensure that the second argument passed in is something that is unitedly washable, the easiest of which is often a string, which can be anything you use to uniquely identify each instance, in this case I am making use of the orderId, which is the DB id for the order being returned as part of the API response.
The example is based off Loops driver application, a driver will have a list of 1 or more tasks on their device, which would be sharing the same business logic like the current status of the task, and will need to be able to perform all the same actions such as progressing the order/updating it's status.
The uniqueness we getting from the provider allows us to ensure they we can use a single state to expose all the business logic and ensure that each of them has access to their own specific state.
Next we will take a look at how Riverpod providers can be accessed within your UI or data classes.
I hope you found this interesting, and if you have any questions, comments, or improvements, feel free to drop a comment. Enjoy your development journey :D
Thanks for reading.