In this article, I will show an example to manage the state in the Flutter application using Redux. For JavaScript developers, Redux is not a sublime and not a new thing. What is it? You will learn about it with me. !!!
Redux is like other tools for state management. It makes the application work consistently, run in different environments, and be easy to test and debug.
Redux contains 3 components: Action, Store, and Reducers. You should understand these definitions.
Below will be an operating principle of a Redux.
In Flutter, there are 2 useful packages, easy to implement: redux and flutter_redux.
To understand Redux in Flutter, let's take a look at the example below:
When the user taps add button (+) or decreases button (-), the number of products to buy to add to the cart. After adding a new (from 0 to 1) or deleting a product (from 1 to 0), immediately the total number of products in the cart on the tabbar will be changed accordingly.
For example, in the figure, when adding a new one it goes from 4 to 5, and when it is deleted it goes from 4 to 3.
Next, below will be the steps to implement the code for the application like the example above.
dependencies: redux: ^5.0.0 flutter_redux: ^0.10.0
Create a redux folder to contain files related to actions, reducers, selectores, ...
import 'reducers.dart'; Store<AppState> createReduxStore() { return Store<AppState>( appStateReducers, initialState: AppState.initial(), middleware: [], ); }
AppState appStateReducers(AppState state, dynamic action) { return AppState( cartItems: cartReducer(state.cartItems, action)); }
class SetCartItems { final List<CartModel> cartItems; SetCartItems(this.cartItems); } class SetUpdateCartItem { final CartModel item; SetUpdateCartItem(this.item); }
final cartReducer = combineReducers<List<CartModel>>([ TypedReducer<List<CartModel>, SetCartItems>(_setCartItems), TypedReducer<List<CartModel>, SetUpdateCartItem>(_updateCartItem), ]); List<CartModel> _setCartItems(List<CartModel> state, SetCartItems action) { return state; } List<CartModel> _updateCartItem( List<CartModel> state, SetUpdateCartItem action) { return state; }
int getTotalCartItem(AppState state) { return state.cartItems.length; }
void main() { Store<AppState> store = createReduxStore(); runApp(App(store: store)); }
class App extends StatelessWidget { final Store<AppState> store; const App({super.key, required this.store}); @override Widget build(BuildContext context) { return StoreProvider<AppState>( store: store, child: MaterialApp( title: 'Đinh Thành Công', theme: ThemeData(), initialRoute: '/', routes: { }, onUnknownRoute: (RouteSettings setting) { return MaterialPageRoute( builder: (context) => const NotFoundScreen()); }, )); } }
At this point, you and I have finished configuring a Redux corresponding to the example above. Next, how to display the number as shown in the picture. Let's go:
class ProductsScreenState extends State<ProductsScreen> { @override void initState() { super.initState(); } int _getTotalPrice() { final store = StoreProvider.of<AppState>(context); return getTotalPrice(store.state); } @override Widget build(BuildContext context) { return StoreConnector<AppState, List<CartModel>>( builder: (context, cartItems) { return Scaffold( body: ListView.builder( shrinkWrap: true, primary: true, physics: const NeverScrollableScrollPhysics(), itemCount: cartItems.length, itemBuilder: (BuildContext context, int index) { return Text('Product name'); }, )); }, converter: (store) => store.state.cartItems); } }
At this point, we just need to re-build the application and wait for the results.
I hope this article is of great value to you. Good luck !!!!