TodoMVC With React Native and Redux

This post is a walkthrough of building a TodoMVC using React Native and Redux.

July 20 Update: There’s a post talking about getting GraphQL to play nicely with Parse Server.

June 23 Update: TodoMVC React Native example now includes a persistence layer using Parse Server and GraphQL - check out the repository for more information.

React Native TodoMVC

Quick start

Note There is sometimes a nasty bug with npm module installs. If you get an error related to a module not being resolved correctly, just rerun npm install so it can pick up missing modules

Walkthrough

Before we begin, there are few things you need to know/be comfortable with. This article assumes you already have some experience with React Native and you are also comfortable with the ideas behind Redux.

We are using our home made React Native boilerplate called Baker boilerplate for this but you do not have to.

Getting started

This will set up a basic React Native project in TodoMVC directory - you will be prompted to enter a name of your app.

Take a look around

Let’s take a look at the app structure that we have so far

Initial app Structure - TodoMVC

Most of the things in the project root directory are part of the standard React Native structure that you get after running react-native init. Now if you take a closer look to the /app directory, you will notice there are already a few additional things in place:

app/setup.js is the entry point to the application, the module is used with index.android.js and index.ios.js in the project root. The module looks like this

If you are familiar with Redux, this should look fairly straighforward: we are connecting application store to the React component tree in our application

app/reducers.js is responsible for composing all the application reducers and making them available to the rest of the application

Notice that the Baker includes a pretty useless reducer called removeThisReducerOnceYouAddALegitOne for you to start with. We will see later how app/reducer.js module is automatically kept in sync when you are using generators to add containers to the app.

Finally, a quick look at app/store.js

This is where our app’s store comes to life taking advantage of the reducers we’ve seen in app/reducers.js as well as some additional middleware (and we’ll see how it’s useful in a second).

Let’s run the app and see what it looks like at this point. Use npm run ios

TodoMVC first run

At this point we have a pretty useless application up and running. Notice we also have a super useful Remote Redux Devtools running next to the app showing us what is going on with the application state. Remember that middleware we added to the store just a few minutes ago - that is what enabled us to have this great sneak peak into our app’s inner workings.

Adding navigation

I wrote extensively about experimental navigation in React Native here.

Once again, Baker (the boilerplate and generator system we are using) allows us to scaffold the entire navigation chunk with a single command:

Adding navigation to React Native project

This will generate a bunch of files to plug in Tab based navigation into the. Let’s reload the app in the simulator and take a look

Basic tab navigation in the app

Head to app/components/MainNavigation/reducer.js and let’s make tabs more relevant to our Todos application:

Our application looks like this now

TodoMVC tabs

Creating TodoList container

Let’s move on to the core of the TodoMVC application - The List. We are gonna use a container generator to create a TodoList container using npm run generate. Start by defining todos reducer that will be responsible managing interactions with todos items

In addition to defining the main reducer function, we are also exposing additional selectors that we can use in the component to select parts of the application state. Let’s take a look at the application state:

Application state with todos

With todos in store, we can now focus on the TodoList container item in app/components/TodoList/index.js

We are gonna take a look at TodoItem component in a minute. Meanwhile notice that our TodoList container is parameterized using filter property that can have one of the following values: all, completed, active. These map nicely to 3 different tabs we’ve defined in the application. getSelector function returns an appropriate selector that we have previously defined in the TodoList reducer module.

Defining TodoItem component

To generate an empty component for the application, we are gonna use npm run generate again, choose Component option and call the new component TodoItem

TodoItem component is parameterized with a todo object and 2 callbacks onToggleCompletion and onDelete. These get passed down from TodoList container that connects it directly via Redux dispatch.

Creating AddTodoItem container

One final missing part is a way to add todos in the application. We are gonna add a simple container responsible for capturing input and creating a new todo item using addTask action defined earlier inside TodoList actions module

Putting it all together

Let’s start by updating MainNavigation container to render appropriate versions of TodoList containers based on the currently selected tab:

Notice how _renderTabContent is responsible for rendering an instance of TodoList container passing along a filter prop corresponding to the key of the current tab.

AddTodoItem is wired on the top level in the App component

Notice the usage of Platform.OS utility to only render AddTodoItem component when running on ios. There are a few minor adjustments that we had to perform (not mentioned in this article) to make sure the Android version of the app looks natural on Android - all the code for both version of the app is included in the example repository

Conclusion

This was the first time I’ve built a fairly simple application using RN (React Native) and it was a lot of fun. I found the tooling to be very nice and helpful. If you understand and like React, RN feels natural. This article is not meant as a shameless plug for our in-house RN boilerplate called Baker but rather a showcase of how one can achieve significant improvement in productivity and happiness with a sane boilerplate+generator combo. Next time you are about to storm out to write an article about JavaScript fatigue, maybe you could write a Yeoman based generator instead and share it with others.

I’ll be doing a followup post on this TodoMVC example to add a pesistence layer to the application.

Links

Subscribe to our mailing list

Every week or so we send out a little email sharing something interesting about JavaScript, React, React Native, Meteor and cakes. We'd love to have you onboard. Also, no spam (pinky swear)