Manage the state of your app using Redux || Flutter💙

Managing state in Flutter is one of the major requirements when our project complexity increases! Redux is a predictable state container for Dart and Flutter apps. It helps to manage our state very efficiently and is robust!

We can say that the state is something (an object) that holds the properties of the widget when it’s built and it might change during the lifetime of the widget!

Redux was initially introduced in JavaScript and then adopted in multiple languages and frameworks. Redux is a predictable state container for Dart and Flutter apps. It helps to manage our state very efficiently and is robust!

Action: Actions can be considered as the user events which contains the information or payload for the Store. In other words, it takes the data from UI and sends it to our Store (Business Logic)

Reducer: In Redux, a reducer is a pure function that takes an action and the previous state of the application and returns the new state. In other words, a Reducer is a function that will perform some operation on the input.

Store: Store is an immutable object tree in Redux. It holds the application’s state and we can access the updated data provided by Reducer using Store.

So here we just created an enum to hold our actions and a static method inside the class which does our main work of updating the values. It takes the current state (of course in case of counter its integer) and the action to be performed!

The StoreProvider<int> provides the store to the entire widget tree and as here our state changes are integer, we have specified the type as int! It takes a parameter store that needs Store type object. Store creates the instance of a particular StoreProvider. It takes the reducer function and initialState. Here our reducer function will be the counterUpdate function that we created inside redux_service.dart and the initial state will be 0!

final store = Store<int>(ReduxActions.counterUpdate, initialState: 0);

Now, wherever we need to rebuild the widget when value is changed, we need to wrap that widget with StoreConnector. Example:

Center(
child: StoreConnector<int, String>(
converter: (store) => store.state.toString(),
builder: (context, count) {
return Text(
'The button has been pushed this many times: $count',
style: Theme.of(context).textTheme.headline4,
);
},
),
),

Basically, StoreConnector is a Widget that gets the store from the nearest ancestor. It takes converter as parameter. The converter converts the store into a model. The resulting model will be passed to the builder function. We have mentioned <int, String> with StoreConnector which means the state will be integer and the converter will return String. So here, we converted our store’s state to string value (store.state.toString()). This string value is passed on to the builder and is stored in the count variable that we used!

StoreConnector<int, VoidCallback>(
converter: (store) {
return () => store.dispatch(CounterActions.Increment);
},
builder: (context, callback) {
return IconButton(
onPressed: callback,
icon: Icon(Icons.add),
);
},
),

Here, we have mentioned <int, VoidCallback> with StoreConnector which means the state will be integer and the converter will return VoidCallback. Inside converter, we have written store.dispatch() . This basically dispatches the action to the reducer, operates on the data based on the action, returns the new state to the store and rebuilds our UI.

You can checkout the entire code on GitHub Repository!

Hope you enjoyed this article!

If you loved it, you can Buy Me A Coffee!

Don’t forget to connect with me on:

Don’t stop, until you are breathing!💙
- Abhishek Doshi

Google Developer Expert — Dart & Flutter 💙