My name is Petar

This is where I write about the things I find interesting

Better MVVM with Xamarin Forms

Let's start with a quick recap of the reasons I am writing this post.

The problem

I find most examples on the web regarding how to write MVVM apps at fault when it comes to choosing where to place the logic about the flow and behaviour of the app - almost all logic is stuffed into the view models. The Model in MVVM is limited to service/repository wrappers and their DTOs. I think we can do better, I think the model has to be much richer and the view models much smaller.
Then I found Redux and I knew exactly what I needed to do, so I ported it to .NET and its name is Reducto. I introduced it in a previous post and there is a quick refresher on that in a following section, but for a more detailed overview, please head over here.

Agenda for this post

In this post the rubber meets the road - Reducto orchestrating your Xamarin Forms app. I am going to focus on a very small part of an app - logging in a user. I think it is sufficiently simple and common and will allow me to focus on the technology necessary for building the feature.

There are some small pieces of glue that I might not talk about here but they are rather simple and live under the Infrastructure folder in the sample project where all material here is taken from. Although the example is with Xamarin Forms, everything should be applicable to other implementations of MVVM too.

Reducto redux recap

Reducto is a keeper of the state for your app. It helps to organize the logic that changes that state.

A quick refresher on the core concepts in Reducto:

Dispatching an action to the store is the only way to change its state.
Dispatching an async action cannot change the state but it can dispatch actions(more about that in a few paragraphs) which in turn can change the state.

Async actions

Let's jump right in and show you the action of logging a user in. It has to be async action since it needs to talk to the "external world"

Let's start with a few observation about async actions in general.

Coming back to this specific action - it returns Task and expects a parameter of type LoginInfo at the time of its invocation, containing the username and password the user has specified. It dispatches actions corresponding to the progress and the outcome of the operation. Also worth noticing is it navigates to another view model upon successful authentication.

The app state

The login async action is dispatching actions before and after the long-running network operation, but how does that affect the view on the screen? - the actions are handled by the mini-reducer responsible for that part of the state and the state is updated accordingly.

Before we look at the reducer let's take a look at the declaration of the app state.

The idea here is that the complete state of the app is broken down into smaller chunks which are handled by dedicated mini-reducers. Divide and conquer my friends, divide and conquer .

The details about DeviceListPageState are intentionally missing since it is not important for this discussion.

The reducer

What follows is an abbreviated version of the App class where all "app logic" lives and the reducer is an important part of it.

A few things here. The reducer for the store is a CompositeReducer and it delegates the responsibility for different parts of the app state to other reducers, in this case - a couple of SimpleReducers, but this sort of brake down can be nested further - here is an example.

Worth noting also is the constructor of SimpleReducer where we can create the initial value for the state this reducer governs. If not provided - the state gets initilized with default values.

View model

Let's take a look at the view model for the LoginPageView

I have a very simple base class for my view models - ViewModel, which helps me find its view based on a very simple convention. Comes handy when I have to do navigation. I am also using the great Fody.PropertyChanged which saves me the annoyance of dealing with INotifyPropertyChanged.

As you can see the view model itself is quite simple. Dispatches the Login async action with the username and password the user has provided and listens for updates to the store and updates its properties accordingly. Store.createAsyncActionCommand is an extension method that creates an ICommand that dispatches an action and is something that is not part of Reducto, but might put in an Reducto.XamarinForms nuget package. For now, you can go see the source code

Conclusion

Needless to say this structuring of an app makes a lot more sense to me:

I know these are still early days for Reducto and may be there are some issues to be addressed but if you like where this is going, please open an issue and let's make it better.

The source code for the full sample app this post is based on can be found on GitHub.

Common guys, hit the comments and let me know what you think .

Post your comment