 Hi everyone! In this article I’d like to show you how to create **Flutter** application using **Redux**. If you don’t know what Flutter is, I encourage you to read my article [Flutter — 5 reasons why you may love it](https://medium.com/@pszklarska/flutter-5-reasons-why-you-may-love-it-55021fdbf1aa) . However, if you know what Flutter is and you’d like to create an application that is **well designed, easy to test and has very predictable behaviour** — then keep going with reading! ### What is Redux? Firstly, let’s start with explaining what **Redux** is. [Redux](https://redux.js.org/) is an application architecture, made originally for JavaScript and now used in applications built with **reactive frameworks** (such as React Native or Flutter). Redux is simplified version of [Flux](https://facebook.github.io/flux/docs/overview.html) architecture, made by Facebook. But what’s all about with Redux? Basically, you need to know three things: 1. there’s a **single source of truth** — your whole application state is kept only in one place (called store) 2. the **state is read-only** — to change the application state you need to dispatch an action, and then new state is created 3. changes are made with **pure functions** — a pure function (to simplify, it’s a function without side effects) takes the previous state and an action, and returns new state Sounds cool, but what are the advantages of that solution? * we have **control over the state** — it means that we exactly know what caused state change, we don’t have duplicated state and we can easily follow data flow * pure **reducer functions are easy to test** — we can pass state, action and test if result is correct * application is **clearly structured** — we have different layers for actions, models, business logic, etc. — so you exactly know where to put another new feature * it’s great **architecture for more complicated** apps — you don’t need to pass state down the whole view tree from parent to child * and there’ one more… #### Redux Time Travel There’s one cool feature possible in Redux — 🎉 **Time Travel**! With Redux and [proper tools](https://pub.dartlang.org/packages/flutter_redux_dev_tools) you can **track your application state** over the time, inspect actual state and **recreate it at any time**. See this feature in action:  Time Travel in action — how cool is that? ### Redux Widgets on a simple example All of the above rules makes data flow in Redux **unidirectional**. But what does it mean? In practice it’s all done with **actions, reducers, store and states**. Let’s imagine application that shows button counter:  1. Your application has some **state** at the beginning (number of clicks, which is 0) 2. Based on that state **view** is rendered. 3. If user taps on button, there’s **action** send (e.g. IncrementCounter) 4. Action is received by **reducer**, which knows previous state (counter 0), receives action (IncrementCounter) and can return new state (counter 1) 5. Your application has new **state** (counter 1) 6. Based on new state, **view** is rendered again So as you can see, generally it’s **all about the state**. You have single app **state**, the **state** is read-only for view, and to create new **state** you need to send action. Sending action fires reducer that creates and emits new application **state**. And history repeats itself.  Redux Data Flow ### Example of Shopping List App with Redux Let me show how Redux works in practice on more advances example. We’ll create a simple ShoppingCart application. In this application there will be functionalities for: * adding items * marking items as checked * and that’s basically all 😎 The application will look like this:  You can see the whole application code on GitHub: [**pszklarska/FlutterShoppingCart** _FlutterShoppingCart - Flutter example of shopping app using Redux architecture_github.com](https://github.com/pszklarska/FlutterShoppingCart "https://github.com/pszklarska/FlutterShoppingCart")[](https://github.com/pszklarska/FlutterShoppingCart) Let’s start with coding! 👇 #### Prerequisite In this article I’ll not show creating UI for this application. You can check the code for [**this Shopping List application before implementing Redux here**](https://github.com/pszklarska/FlutterShoppingCart/tree/a8120a23232a05d380384bb377f3994ef65ad221). We’ll start with coding from this point and we’ll add Redux to this application. If you’ve never used Flutter before, I encourage you to try a [Flutter Codelabs from Google](https://codelabs.developers.google.com/codelabs/flutter/). #### **Setup** To run with Redux on Flutter, you need to add dependencies to your `pubspec.yaml` file: flutter\_redux: ^0.5.2 You can check the newest version on [flutter\_redux](https://pub.dartlang.org/packages/flutter_redux) package page. #### Model Our application needs to manage adding and changing items, so we‘ll use simple `CartItem` model to store single item state. **Our whole application state will be just list of CartItems**. As you can see, CartItem is just a plain Dart object. class **CartItem** { String name; bool checked; **CartItem**(this.name, this.checked); } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/model/CartItem.dart) #### Actions Firstly, we need to declare **actions**. Action is basically any **intent that can be invoked to change application state**. In our application we’ll have two actions, for adding and changing item: class **AddItemAction** { final CartItem item; **AddItemAction**(this.item); } class **ToggleItemStateAction** { final CartItem item; **ToggleItemStateAction**(this.item); } > [Note: Here’s the full source code for this file](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/redux/actions.dart) #### Reducers Then, we need to tell our application what should be done with those actions. This is why **reducers** are for — they simply **take current application state and the action, then they create and return new application state**. We’ll have two reducers methods: List<CartItem> **appReducers**(List<CartItem> items, dynamic action) { if (action is AddItemAction) { return **addItem(items, action)**; } else if (action is ToggleItemStateAction) { return **toggleItemState(items, action)**; } return items; } List<CartItem> **addItem**(List<CartItem> items, AddItemAction action) { return List.from(items)..add(action.item); } List<CartItem> **toggleItemState**(List<CartItem> items, ToggleItemStateAction action) { return items.map((item) => item.name == action.item.name ? action.item : item).toList(); } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/redux/reducers.dart) Method `appReducers()` delegates the action to proper methods. Both methods `addItem()` and `toggleItemState()` return new lists — that’s our new application state. As you can see, **you shouldn’t modify current list**. Instead of it, we create new lists every time. #### StoreProvider Now, when we have actions and reducers, we need to provide place for storing application state. It’s called **store** in Redux and it’s **single source of truth** for our application. void main() { **final store = new Store<List<CartItem>>( appReducers, initialState: new List());** runApp(new FlutterReduxApp(store)); } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/main.dart) To create store, we need to pass **reducers** methods and **initial application state**. If we created the store, we must pass it to the **StoreProvider** to tell our application than it can be used by anyone who wants to request app state: class FlutterReduxApp extends StatelessWidget { final Store<List<CartItem>> store; FlutterReduxApp(this.store); @override Widget build(BuildContext context) { **return new StoreProvider<List<CartItem>>( store: store, child: new ShoppingCartApp(), );** } } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/main.dart) In the above example `ShoppingCartApp()` is main application widget. #### StoreConnector Currently we have everything except… actual adding and changing items. How to do that? To make it possible, we need to use **StoreConnector**. It’s a way to **get the store and make some action with it or read it’s state**. Firstly, we’d like to **read current data and show this in a list**: class ShoppingList extends StatelessWidget { @override Widget build(BuildContext context) { return new **StoreConnector<List<CartItem>, List<CartItem>>**( **converter: (store) => store.state, builder: (context, list)** { return new ListView.builder( itemCount: list.length, itemBuilder: (context, position) => **new ShoppingListItem(list\[position\]));** }, ); } } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/list/shopping_list.dart) Code above wraps default `ListView.builder` with `StoreConnector`. StoreConnector can take current app state (which is `List<CartItem>`) and map this with `converter` function to anything. For purposes of this case, it’ll be the same state (`List<CartItem>`), because we need the whole list here. Next, in `builder` function we get `list` — which is basically list of CartItems from `store`, which we can use for building ListView. Ok, cool — we have reading data here. Now **how to set some data?** To do it, we’ll use also **StoreConnector**, but in a slightly different way. class AddItemDialog extends StatelessWidget { @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, OnItemAddedCallback>( converter: (store) { **return (itemName) => store.dispatch(AddItemAction(CartItem(itemName, false)));** }**,** builder: (context, callback) { return new AddItemDialogWidget(**callback**); }); } } **typedef OnItemAddedCallback = Function(String itemName);** > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/add_item/add_item_dialog.dart) Let’s look at the code. We used **StoreConnector**, as in the previous example, but this time, instead of mapping list of CartItems, into the same list, we’ll map this into `OnItemAddedCallback`. This way we can pass callback to the `AddItemDialogWidget` and call it when user adds some new item: class AddItemDialogWidgetState extends State<AddItemDialogWidget> { String itemName; **final OnItemAddedCallback callback; AddItemDialogWidgetState(this.callback);** @override Widget build(BuildContext context) { return new AlertDialog( ... actions: <Widget>\[ ... new FlatButton( child: const Text('ADD'), **onPressed: () {** ... **callback(itemName); })** \], ); } } > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/add_item/add_item_dialog.dart) Now, every time user press “ADD” button, the callback will dispatch `AddItemAction()` event. Now we can do very similar thing for toggling item state: class ShoppingListItem extends StatelessWidget { final CartItem item; ShoppingListItem(this.item); @override Widget build(BuildContext context) { return new **StoreConnector<List<CartItem>, OnStateChanged>**( converter: (store) { **return (item) => store.dispatch(ToggleItemStateAction(item));** }, builder: (context, callback) { return new ListTile( title: new Text(item.name), leading: new Checkbox( value: item.checked, **onChanged: (bool newValue) { callback(CartItem(item.name, newValue)); }),** ); }); } } **typedef OnStateChanged = Function(CartItem item);** > [Note: Here’s the full source code for this file.](https://github.com/pszklarska/FlutterShoppingCart/blob/4756839d5749dfa36073e830b208bb45cb5f8874/lib/list/shopping_list_item.dart) As in the previous example, we use **StoreConnector** for mapping `List<CartItem>` into `OnStateChanged` callback. Now every time checkbox is changed (in `onChanged` method), the callback fires `ToggleItemStateAction` event. ### Summary That’s all! In this article we created a simple Shopping List application using Redux architecture. In our application we can add some items and change their state. **Adding new features to this application is as simple as adding new actions and reducers.** Here you can check the full source code for this application, including **Time Travel** widget: [**pszklarska/FlutterShoppingCart** _FlutterShoppingCart - Flutter example of shopping app using Redux architecture_github.com](https://github.com/pszklarska/FlutterShoppingCart "https://github.com/pszklarska/FlutterShoppingCart")[](https://github.com/pszklarska/FlutterShoppingCart) Hope you liked this post and stay tuned for more! 🙌