React Routing and State 3 ways: part2

Michael Kulinski
8 min readOct 24, 2016

If you like this article please check out my podcast, The Developer Experience!

In part 1 of this series we showed how you can use React Router to build a simple two page application. I recommend reading part 1 before jumping in on part 2.

In this section we will be showing you how to add Redux to a React Router application.

We’re going to be adding quite a few new files to our application in order to accommodate Redux. Here is what your folder structure should look like after the end of this tutorial (with blog being the name of your root dir):

The first step is to use npm to install all of our new Redux and React Router libraries and dependencies. Open up your console and run the following command in your application directory:
npm install — save redux react-redux react-router-redux

This command will install the following libraries:

redux
It’s a common misconception that Redux was created for React, when in fact, Redux is just a JavaScript library that people happen to use with React. Because of this, we have to install:

react-redux
React Redux connects our Redux store to our React application.

react-router-redux
Not only do we have to bring in React Redux in order for our application to to use Redux, we also have to connect React Router to Redux. This requires yet another library called react-router-redux. (confused yet?) We use react-router-redux to be able to sync the history between our React Router components and our Redux store.

Below is a screenshot of our new index.js file with all of our newly installed dependencies and components. I wanted to provide you with this first so you can visualize the main areas of our application that will need to be changed.

index.js

Later on I will go through line by line and explain what each of these new components and routes are doing.

First things first, we need to alter our components.js file. The main point to understand here is that we need to bring all of our this.state calls out of our current components and change our this.props calls to props. This is because Redux is now controlling all of our application state. The big benefit here is that we can turn all of our components into stateless components.

Let’s start with our new top level component Home.

components.js

The only thing we changed here is adding the line: {React.cloneElement(props.children, props)} so that all of the children of our top level Home component will receive its props when they’re rendered.

Next we need to create a new Root component:

components.js

As you might have noticed in the first screenshot from our new index.js file, we have a new top level component. The only purpose of our top level component is to render our navigation menu and wrap its children with props. So in order for us to still show our welcome message, we need to create a new component and set it as our IndexRoute in our index.js file.

index.js

The next step is to alter our Page1 component:

As you can see, Page1 has received a major overhaul. Now that we are relying on Redux to hold all of our state, we can turn Page1 into a stateless component. Because Page1 is a child route of our Home component, it’s automatically sent Home’s props because Home renders all of its children with React.cloneElement(props.children, props).

All we need to do is pass InputName our updateUserName action (we will explain Redux actions in the Redux section) and history from our new react-router-redux function that is connected to our Redux store.

Speaking of InputName, here is what our new InputName component looks like:

Not too different from our previous version. We’ve just added a function that onSubmit will trigger. This new function handleClick will trigger our Redux updateUserName action and then push ‘/page2’ to our new react-router-redux history function instead of using the React Router history function.

Once our new history function is triggered, our view will be changed and our new Page2 component will render:

components.js

As you can see, Page2 hasn’t changed too much either. The main difference is that because Page2 is a direct child of Home, just like Page1, it too will receive Home’s props. So all we have to do is grab the username field from our new Redux store.

That covers all the changes to our components.js file. Now lets dive in and start creating the Redux portion of our application.

Adding Redux

NOTE: If you’re completely new to Redux, I recommend you check out the documentation to learn the basics.

Let’s start by creating a new file called actionCreators.js. This file will hold our Redux actions:

actionCreators.js

Because this is a simple application, we only need one action creator. Action creators take in an object and return an object. The only thing required of the return object is that it has to have a type key that contains a string. This type string will be used in our reducer to change our store. This will become much clearer in the next section when I show you our reducer function.

In our updateUserName action we gave our action a type of UPDATE_USERNAME because that’s what we want to do with this action, update the username state. Our action also takes in a payload which will contain our username, so we will return that out as well.

Next we need to create a reducers.js file. This file will contain all of our reducers and will also be the place where we integrate our reducers with our new react-router-redux library.

reducers.js

Reducers take in two parameters, state and action. State in our case will initially be an empty object. The action parameter is received from our actions being called. Like I said in the last section, each action has a type key. This is to tell our user reducer which case statement needs to be fired. In our case we only have one, but typically applications will utilize many cases. Because the action is fired every time any item in our store needs to change, we need to return state by default.

Below our user reducer we’re using the Redux combineReducers function to combine our reducer with our react-router-redux routing. In most applications you will have more than one reducer, so you will list each one out in your combineReducers function.

As you might have noticed from the index.js picture above, our root route is now using the component ReduxHome. ReduxHome is just our new Home component that we wrap our Redux store and props around.

Let’s make that now. Create a new file called ReduxHome.js and place the following code inside:

ReduxHome.js

We need to use React Redux’s connect method to connect the mapDispatchToProps and mapStateToProps functions to our application through our top level component Home. We now have a new constant ReduxHome that will be our top level route for React Router.

We’ve mentioned our Redux store a few times throughout this tutorial, so let’s go ahead and create a store.js file.

store.js

As you can see, from our store.js file above, creating and connecting your Redux store to React Router is no simple task.

1. You have to create an initial state for your application. The confusing part here is that the top level keys in your defaultState object have to be the same as the keys from when you combined your reducers in reducers.js using the combineReducers function:

reducers.js

For this application we only have one reducer key, user so we have to store the username default state there.

2. After that you need to create your react-router-redux middleware and pass it the React Router browserHistory function.

store.js

3. Now we need to create our Redux middleware that triggers every time we change our store.

store.js

4. We need to also create and export our store using the Redux createStore method and pass it all of our reducers as well as our default state object and the middleware we created above.

store.js

5. The last step in our store.js file is to create our history and sync it with React Router’s browserHistory function as well as our store.

store.js

Next we need to change our ReactDOM.render method so that our new ReduxHome component renders the rest of our components. That way we can pass our Redux store and actions to the rest of our application. In the last blog post we had to resort to using route params in React Router to pass props. This is a terribly unsecure and inefficient way to pass props to components. We will alter our index.js file to look like this:

index.js

As you can see, we had to change our routes A LOT. The most important part to note is that we’re bringing in a Provider component and wrapping it around our router. We’re also importing our new ReduxHome and Root components, as well as our Redux store and react-router-redux history. Another important note here is that we also imported IndexRoute from React Router. This component will render Root every time a user visits the root “/” path.

That’s it for part 2 of our three part series on building an application with React, Redux and React Router. Up next we will show you a much less verbose and we believe, better way to create a React application with routing and higher state!

--

--