Flutter Riverpod Tutorial Part 6: Riverpod Scopes and Overriding Providers

Search for a command to run...

No comments yet. Be the first to comment.
In this series, I'll cover every concept of Riverpod in a comprehensive manner, so that any user can understand total ins and outs of any Riverpod concept.
In this tutorial we'll dive into advanced Riverpod patterns. Sections Covered: Using the family Modifier Using the AutoDispose Modifier Keeping Providers Alive with keepAlive Declaring Dependencies with dependencies 1. Using thefamily Modifier ...
While I generally write about Flutter. This problem has been bugging me for a while and there seem to be limited resources to find a solution. So for anyone who is looking for a solution. Here you go: Type edge:flags into the address bar and open it...
In this tutorial, we’ll go through covering interceptor, which is a very crucial feature of Dio. You can find the entire source code for the project here: dio_tasker Understanding Interceptors: What is an interceptor? An interceptor in Dio is a powe...

In this part, we’ll enhance our Task Manager app by parsing JSON responses and handling different types of errors. We’ll use Dio’s built-in error handling mechanisms. You can find the source code of the entire app here: dio_tasker Parsing JSON Respon...

While building apps in Flutter is extremely fluid and wonderfully intuitive. We obviously know that we can’t build the next TikTok or Twitter by only building offline apps. Which is why we absolutely need internet capabilities in our Flutter apps. Th...

Understanding when to use setState in Flutter is crucial for managing our app’s state effectively. Here’s a detailed guide: When to use setState ? Updating the UI: Use setState when we need to update the UI in response to changes in the internal sta...

In this tutorial, we'll explore the use of ProviderScope for creating isolated sections in your app and learn how to override providers for different configurations and testing. We'll also look at practical examples to illustrate these concepts.
Using ProviderScope for Isolated Sections
Overriding Providers
Practical Examples
ProviderScope for Isolated SectionsProviderScope is used to create a scope within which providers can be accessed and managed.
This allows for creating isolated sections in your app where specific providers can be overridden or reset without affecting the rest of the app.
Here's our code :
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
//Let's define a simple counterProvider
final counterProvider = StateProvider<int>((ref) => 0);
void main() {
runApp(
const ProviderScope(child: MyApp()),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.dark,
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Riverpod ProviderScope Example'),
),
body: SizedBox(width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const ProviderScope(child: CounterWidget()),
ProviderScope(
overrides: [counterProvider.overrideWith((ref) => 100)],
child: const CounterWidget()),
],
),),
);
}
}
class CounterWidget extends HookConsumerWidget {
const CounterWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider);
return Column(
children: [
Text('Value: $counter',
style: const TextStyle(fontWeight: FontWeight.bold,
fontSize: 24),),
ElevatedButton(onPressed: (){
ref.read(counterProvider.notifier).state++;
}, child: const Text('Increment'),)
],
);
}
}
So these are the two things we used in the above code:
ProviderScope: Creates an isolated scope for providers.
overrides: Allows you to override providers within the scope.
You can find the source code here: ProviderScope Override
And as you can see the app works perfectly with different values
You can see the output here:

Overriding providers is useful for testing or when you need different configurations for specific parts of your app.
You can override providers by using the overrides parameter in ProviderScope.
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
void main() {
runApp(
const ProviderScope(child: MyApp()),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.dark,
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Overriding Providers Example'),
),
body: Column(
children: [
const ProviderScope(child: GreetingWidget()),
ProviderScope(
overrides: [greetingProvider.overrideWithValue('Hello Riverpod')],
child: const GreetingWidget()),
],
),
);
}
}
final greetingProvider = Provider<String>((ref) => 'Hello Word!!');
class GreetingWidget extends HookConsumerWidget {
const GreetingWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final greeting = ref.watch(greetingProvider);
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
greeting,
style: const TextStyle(fontSize: 24),
),
);
}
}
You can find the source code here: Overriding
Use cases for the Overriding:
Isolated configurations
Overriding for Testing