Blog

React Native Tutorial with React-Navigation, Redux and Redux-ORM

Introduction


About one and a half year ago we switched from native app development to React Native after some comprehensive research and comparisions.

So we have worked on the React Native for 18 months now, and we have recently released our first product, Simple Mobile CRM, which is available for free in both App Store and Google Play. Both iOS and Android versions are purely based on React Native, and no native module is used at all. You may take a look of the performance if you are interested.

So this article is not just a quick review from React Native 3-month beginners, instead we try to put some consolidated experiences here. We cannot say for sure if it's the de-facto best practice, but we sure researched a lot and refactored a number of times during the development. These are all hard-learned lessons.

This article assumes basic knowledge of React Native and Redux. Here is a great redux tutorial if you are not yet familiar with it yet.

There are two things that must bear in mind when developing React Native,

  1. Things change fast in the world of React Native. Well, programming world in general changes fast, but it's nothing when compared to world of React Native. Most of the libraries you use, no matter how main stream it is, is likely to have big, non-backward compatible upgrade every 6 months, and usually it's even faster than that.

  2. If the app involves at least moderate complexity of data-UI interaction, you better select some sort of Redux. There are more than one library for this, but you better pick up one whenever possible.

What is Redux

Redux is a predictable state container for JavaScript apps.

Ideally, we should map the state of the running app to the redux store, in a reasonable way. There are two important questions:

  • How are we going to bind each scene's state with the redux store?
  • And what is the right way to manipulate redux store?

These questions are important, not because they are difficult to Google out the resources, but because of the contrary, there are too many alternatives out there. After much time of struggling, here is what we come up eventually. And we believe this is a better way to balance the code efficiency and reliability.

In the coming sections we would build an example app to illustrate a full-blown redux, using two important libraries:

  • A highly hackable routing and navigation system: react-navigation
  • A powerful yet lightweight data managing/binding method: redux-orm

The full source code of the app sample could be found here:

https://github.com/bartsolutions/RNMovie

Navigation


Today, we'll build a simple app of called 'Movie Fans'.

It will include:

  • Side Bar
  • Movie list page
  • Movie detail page
  • Movie create and edit page
  • Comment List page

To get the general idea of this app, let's take a look at the AppNavigator.js . The navigation related code is quite self-explanary:

Here's how the navigation looks like:

Data Strucutre with Redux-ORM

With the help of redux-orm we can define a Model for object relational mapping, similar to Django models.

Our app has two models, which are Movie and MovieComment, and they are connected using a ForeignKey.

Let's take a quick look at models.js

Data Binding

Next thing we need to do is to bind the models with the scenes, here are the bindings we want.

First, create selectors for the scenes (selectors.js):

Now, connect movieListSelector to MovieList sence (movielist.js)

Also connect selector to MovieDetail sence (movieDetail.js)

As we can see:

  • The selector and scene were connected via mapStateToProps function, using a dynamically created selector.

  • When View button was clicked in MovieList scene, a navigation params will be passed to MovieDetail scene so the selector can use it for the binding.

Manipulating the Redux Store

Now the scene and the store are connected via selectors. Next thing we need is to activate various actions (CREATE, EDIT and DELETE of movie and CREATE of comment), i.e. we need to manipulate the store.

How are we going to do that? Of course, use the reducers

Let's create a reducer in src/data/reducer.js first:

Now dispatch those actions in different scenes:

For Movie Creation or Update in createOrEditMovie.js

So we can do this:

For Movie Deletion in movieList.js

So we can do this:

Create MovieComment in movideDetail.js

So we can do this:

Closing

Before Redux-ORM was adopted, we were using per-scene redux store. Back then every scene's state was self-sustained. For example, the movie detail scene will have not only its own data, but also all of the related comments as well. And that causes two big headaches:

  • When a new comment was created, we need to remember to update both states of comment list scene and movie detail scene. If the relation gets more complicated (Like Many-To-Many), it's very hard to keep all the scene's data aligned.
  • Since many scenes got duplicated information the store will get bloated as time goes on.

Now:

  • All data are handled and optimized by Redux-ORM, there is no (or very few) duplicated data
  • A full model-based database is mapped into device, so the app appears as more responsive as most data could be collected from the local database.
  • Selectors can handle the data binding automatically (even with relational data).

The full source code from this article could be found in Github.

Hope this article can bring some insights to your RN development, and stay tuned as we will share more in coming weeks.