Using Redux with Xamarin Forms — Part 2— State, Reducer and Actions
Folder structure
First we need to create the nessesary folders and files.
I like to seperate app features in own feature folders. So my Order feature folder structure look like this:
Domain
The domain folder contains all domain specific parts. In this examples the Models file which contains all nessesary Models as Records.
Presentation
Contains the XAML-Page and the ViewModel
State
The state contains all Redux related parts:
- The whole state of the Order
- Actions which can be dispatched
- Reducers which modify the store based on Actions
- Selectors to select specific parts of the store for the UI
In the next parts i implement one use-case after another to fill this whole files with content.
Implement the Redux Parts
The user should see all available products to buy.
Models
Models.cs
- Two wrappers for int ProductId and ShoppingCartItemId
- A Product which is available with Price and Description.
- A ShoppingCartItem which contains the selected Product and the desired amount
Actions
We need to trigger the loading of products at Page-Load
Actions.cs
- InitializeOrderAction — Initiate the loading of the products
- InitializeOrderActionSuccess — Is dispatched if the loading was successfull and returns the list of ShoppingCartItems
- InitializeOrderActionFailure — Is dispatched when the loading throws an exception
Entities
When dealing with collections, you often repeat the same process to add, update and remove entity from your collection state. Entities in ReduxSimple simplify the managing of such cases in the reducer.
There is a little boilerplate code involved but you will see the benefits later.
State
The state represents the UI-State of the order
We define ShoppingCartItems which uses the ShoppingCartItemEntityState-helper for representing the ShoppingCartItems list.
The Sum property represent the sum in € of all products.
The IsLoading property indicates the the view is busy.
Adding to RootState
After OrderState is created we can add it to our RootState:
Adding to RootReducer
Here all reducers from all subreducers are combined.
We have only one reducer.
Selectors
Based on what you need, you can observe the entire state or just a part of it.
Selector allows you to select parts of the State.
First we create a selector for the OrderState. This selector selects only the OrderState from the RootState and can be reused to select deeper parts of OrderState.
The second selector selects to the Sum changes.
The third selector selects to the IsLoading changes.
The fourth selector selects with a little magic from ReduxSimple to the ShoppingCartItem-List changes from OrderState.
Reducers
This reducer reacts on InitializeOrderAction and fills the ShoppingCartItem list with mock data.
You can see how i’am using the previosily created ShoppingCartItemAdapter to populate the property.
I’am also using C#9 with-Expressions to create a new state without mutating it 🤩. It creates a new state where only ShoppingCartItems has a new value, the rest of the properties remain unchanged.
In the next part, when we use effects, we will get real data from an api and create a new InitializeOrderActionSuccess from the effect.
ViewModels and View
The last part is the linking of all parts in the ViewModel and the view.
OrderViewModel
The ViewModel selects ShoppingCartItems from the store and fills the CartItems ObservableCollection when something changes.
To trigger the loading of the list the InitializeOrderAction must be dispatched to the store.
OrderPage
In the first iteration of OrderPage we can see the loaded mock data.
Summary
We have implemented the store parts:
- State
- Actions
- Selectors
- Reducers
We also used this parts in the ViewModel and View.
You can find the current state of the app’s code here:
What’s next
- Using effects to load data from an external api
- Implementing the other parts of the order
- Eventually using some other reactive concepts