Flutter Riverpod Tutorial Part 5: Riverpod Hooks

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 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. Sect...
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...

We are going to create a new app to use Flutter hooks. You can find the source code here: learn_flutter_hooks
If you want to know more about Flutter Hooks. You can read it here: https://harishkunchala.com/flutter-hooks-everything-to-know-about-them
So lets look at few examples to understand Riverpod Hooks
Since we have create a new project we can add the following dependencies:
hooks_riverpod
flutter_hooks
flutter pub add hooks_riverpod flutter_hooks
Let's setup the main.dart to accept Riverpod
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'pages/home_page.dart';
void main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
Let's check it out
// 1. Create a StateProvider to hold the counter value:
final localCounterProvider = StateProvider<int>((ref) => 0);
class CounterHookPage extends HookConsumerWidget {
const CounterHookPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 2. Access and display the counter value
final count = ref.watch(localCounterProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Hooks 1: CounterProvider'),
),
body: Center(
child: Text(
'Count: $count',
style: const TextStyle(fontSize: 24),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 3. Update the Counter value
ref.read(localCounterProvider.notifier).state++;
},
child: const Icon(Icons.add),
),
);
}
}
class FavoriteNotifier extends StateNotifier<bool> {
FavoriteNotifier() : super(true);
void toggleFavorite() => state = !state;
}
final favoriteStateNotifierProvider =
StateNotifierProvider<FavoriteNotifier, bool>((ref) => FavoriteNotifier());
class AnimationHooksPage extends HookConsumerWidget {
const AnimationHooksPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isFavorite = ref.watch(favoriteStateNotifierProvider);
final animationController = useState(
useAnimationController(duration: const Duration(milliseconds: 300)));
useEffect(() {
if (isFavorite) {
animationController.value.forward();
} else {
animationController.value.reverse();
}
return null;
}, [isFavorite]);
return Scaffold(
appBar: AppBar(
title: const Text('Favorite Button'),
),
body: Center(
child: ScaleTransition(
scale: animationController.value,
child: IconButton(
iconSize: 100,
icon: Icon(
isFavorite ? Icons.favorite : Icons.favorite_border,
color: isFavorite ? Colors.red : Colors.black,
),
onPressed: () {
ref.read(favoriteStateNotifierProvider.notifier).toggleFavorite();
},
),
),
),
);
}
}
final userDataProvider = FutureProvider<Map<String, dynamic>>((ref) async {
final apiResponse =
await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users/1'));
if (apiResponse.statusCode == 200) {
return jsonDecode(apiResponse.body);
} else {
throw Exception('Failed to load user');
}
});
class FutureProviderHooksPage extends HookConsumerWidget {
const FutureProviderHooksPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsyncData = ref.watch(userDataProvider);
final animationController = useState(useAnimationController(duration: const Duration(milliseconds: 500)));
useEffect((){
userAsyncData.whenData((data){
animationController.value.forward();
}
);
return null;
},[userAsyncData]);
return Scaffold(
appBar: AppBar(title: const Text('Getting the User'),
),
body: Center(child: userAsyncData.when(data: (jsonUser) => ScaleTransition(
scale: animationController.value,
child: ListTile(title: Text('${jsonUser['name']}'),
subtitle: Text('${jsonUser['email']}'),),
), error: (error, stackTrace) => Text('Error : ${error.toString()}'), loading: () => const CircularProgressIndicator()),),
);
}
}