In today’s blog, we’re going to take a closer look at Flutter Hooks. Flutter Hooks is a fantastic library that takes the development of Flutter to the next level.
What Are Flutter Hooks?
If you’re using Flutter, you’ve probably heard of Flutter Hooks. It’s an extension to Flutter that gives you a more organized way to manage state and other side effects. Basically, it’s a React Hooks-style extension that gives you a bunch of hooks to keep track of your widget’s state.
This makes it way easier to write the code you need and helps avoid the common issues and mistakes that come with keeping track of your Flutter app’s state.
Additionally, you may read more about Mobikul’s Flutter app development services.
Benefits of Flutter Hooks:
- Simplified State Management: Flutter Hooks makes it easy to keep track of your widget’s state with hooks like useState.
- No StatefulWidget: With Flutter Hooks, you can often avoid creating
StatefulWidget
classes, reducing the boilerplate in your code. - Reactive UI: Flutter Hooks provides hooks like
useEffect
anduseMemo
that help you make your UI components react to changes in state. - Improved Code Readability: Your code becomes more concise and easier to read. It’s easier to understand what your components are doing when using hooks.
- Better Performance: Hooks can help you optimize your app’s performance, as they allow you to minimize unnecessary widget rebuilds.
Implementation
Create new project and add the following dependency into your project
1 |
flutter_hooks: ^0.20.3 |
Types of Flutter Hooks
useState : Manages local state of app we do not need to use setState. Allows to create a variable and subscribe to it, Update the UI in response of user interaction or any other event.
useEffect
: With this hook we do not need to worry about initializing something in initstate() or manually disposing the controllers and streams in dispose() method.
useMemoized
: Hook memoizes complex objects to achieve optimal performance in an app. Caches the Heavy functions in first call, Later when the HookWidget rebuilds, useMemoized
will return the previously created instance.
useRef
: allows you to create mutable references to elements, values, or objects in your functional Flutter components without causing the component to re-render when the referenced value changes.
useCallback
: hook is a powerful tool that allows you to memoize functions and prevent unnecessary re-creations of functions during re-renders.
useState Hook
Create a new dart class (CounterApp), Import flutter_hooks and extends CounterApp class with HookWidget as shown below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class CounterApp extends HookWidget { const CounterApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final counter = useState(0); return Scaffold( appBar: AppBar( title: const Text("Counter App Hooks"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'You have pushed the button this many times: ', ), Text( '${counter.value}', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => counter.value++, child: const Icon(Icons.add), ), ); } } |
Above example code contains state “counter”, which is managed with useState() Hook.
- It is initialised with value 0.
- state of the widget is accessed with the help of .value property (counter.value).
- When Floating action button is pressed the value of state is incremented by 1 and the UI is updated by useState method.
Learn more about state management in flutter.
useEffect
Hook
useEffect method helps to remove boiler plate code of statefulWidget we can use this as shown below :
1 2 3 4 5 6 7 8 9 10 |
useEffect(() { // initialization same as initState in StatefulWidget return () { // dispose }; }, [] // same as didUpdateWidget in stateful widget // null: call useEffect in every change // empty list: call useEffect only once on the first time // list with items: call useEffect when any of the items on the list change. ); |
create a new stateless widget (TimerApp) and extends it with HookWidget and write code as shown below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class TimerApp extends HookWidget { const TimerApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final seconds = useState(0); late Timer timer; useEffect((){ timer = Timer.periodic(const Duration(seconds: 1), (timer) { seconds.value = timer.tick; }); return (){ timer.cancel(); }; }, []); return Scaffold( appBar: AppBar( title: const Text("UseEffect Hook example"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Timer seconds : ${seconds.value}", ), ], ), ) ); } } |
useMemoized
Hook
useMemoized
memoized or cache the instance of complex object in memory.
useMemoized
accept a callback function that passes to the hook then useMemoized
call and store the result the result of function in memory.
1 |
final result = useMemoized(() {}, [Keys]); |
In above code of useMemoized
it has second optional arguments called list of keys similar to useEffect Hook.
This key argument is a dependency list that specifies whether the Memoized function executed when the widget is rerendered.
Use Memoized checks the keys of a widget when it rebuilds to see if the previous values have changed. If there is at least one change in the keys, then the function callback called and save new result in cache.
useRef
Hook
Create a new stateless widget CounterApp and extends with HookWidget as below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class CounterApp extends HookWidget { const CounterApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // Create a reference to store a value (initial value: 0) final counter = useRef(0); // Access and update the value without causing a rebuild return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Counter: ${counter.value}'), ElevatedButton( child: Text('Increment'), onPressed: () { counter.value++; // Update the counter without rebuilding the widget }, ), ], ), ), ); } } |
useRef hook : allows you to create mutable references to values that persist across renders without causing the widget to rebuild.
It only store the value, it doesn’t make it available to render to the screen.
useCallback Hook
It helps to optimize your Flutter app’s performance by memoizing callback functions.
1 2 3 4 5 |
final cachedFunction = useCallback((){ // Statements // code for the callback function } [keys]); |
useCallback Hook works :
- When using the useCallback hook, a callback function is passed to the hook along with a dependency list. The useCallback function is then memoized and only recreate when the dependencies are changed.
- By memoizing the callback, you can prevent unnecessary widget rebuilds when the dependencies remain the same
Conclusion
Thanks for reading this article ❤️
I hope this blog will help you to learn about how to use flutter hooks and you will be able to implement it. For more updates, make sure to keep following Mobikul Blogs to learn more about flutter and android.
Check out these interesting flutter topics:
- https://mobikul.com/flutter-state-management-using-bloc-pattern/
- https://mobikul.com/flutter-app-state-management-using-provider/
Happy Learning ✍️