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.
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
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.
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
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
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.
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:
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
Head to app/components/MainNavigation/reducer.js and let’s make tabs more relevant to our Todos application:
Our application looks like this now
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:
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
I’ll be doing a followup post on this TodoMVC example to add a pesistence layer to the application.
- Source code for this example
- Yeoman based RN generator by The Bakery
- Baker RN boilerplate by The Bakery
- Max Stoiber’s React Boilerplate, inspiration for Baker
- Follow us on Twitter for more goodness