Getting started with create-react-app, Redux, React Router & Redux Thunk

tldr; You can clone my GitHub repo and skip the walkthrough or watch videos like this on YouTube.

We are going to build the following

Our working example 🤘

There is a fantastic tool on the block endorsed by React that boasts “no configuration necessary”.

I use create-react-app for every new React application. It’s so good 💯.

The great thing Create React App has bundled is the eject tool, which allows you to completely disconnect and add your own advanced configuration.

Seriously though, this is not required to add things like Redux, React Router & Redux Thunk.

This tutorial assumes you have a good fair understanding of Redux. Check out this tutorial on Egghead by Dan Abramov if you want to see what all the Redux fuss is about.


Let’s get to it!

Let’s go ahead and create a new React app.

npx create-react-app react-redux-example
cd react-redux-example

Before we add any code, let’s go ahead and install all our dependencies.

npm install --save redux react-redux react-router-dom connected-react-router redux-thunk history

Note: All of the files we’ll create below are to be saved within the src directory.


1. The Store

Everything in Redux belongs in a single store. Let’s configure our store to understand react-router and redux-thunk.

./src/store.js

Within our store, we’re importing a few core modules from Redux that allows us to create a custom global store. connected-react-router and redux-thunk are both known as middleware to Redux and we need to configure our store to treat them that way.

You’ll notice we’re importing a file we haven’t yet created called rootReducer. This is essential to Redux. We’ll come back to Reducers later but for now, create a file called ./src/modules/index.js so we can satisfy our Store.

./src/modules/index.js

Our store const creates a store using the Redux createStore function. It accepts a rootReducer, initialState and an enhancer in this example.

Our history const syncs our browserHistory with our store and must be exported so we can use it within our routes later.

We also must export our storeconst as the default module so that it can also be used later.


2. Routes

This tutorial uses React Router v4 which allows us to mount components anywhere inside our application when a given url matches our defined parameters.

In previous versions of React Router you might see files like routes.js which contain a long list of nested routes but React Router v4 does routing a little differently.

Our router history is managed inside our Redux store which we created in the first section and is passed down via something called ConnectedRouter which we will implement later.

We’ll get started by defining which components to show at what url in our first container component App.


3. Containers

First, create our App component that renders navigation and any matching routes inside a main tag.

./src/containers/app/index.js

Now let’s create our Home component that we defined to show at the exact path of /.

./src/containers/home/index.js

This should be straight forward for those who have used Redux before but what is special in this example is we can import push from connected-react-router and use within our action creator.

Since our Store knows about connected-react-router it can manage and act on routing actions. Magic! 💥

Finally, create the About component to allow our router to actually do something.

./src/containers/about/index.js

4. Rendering our app

The time has come to mount our application.

We need to tell react-dom to render our application with the correct store and browser history data. We do this by using the ConnectedRouter export given to us by React Router v4. ConnectedRouter has access to the store given to Provider so you don’t need to worry about passing data through any additional props.

React Router magic 💥!

src/index.js

5. Adding Redux Thunk

It’s 2018 and your React application is most likely going to be crawling with async functions. Redux Thunk is middleware for Redux that allows you to write action creators that return a function instead of an action.

That totally made no sense, so let’s see an example!

Let’s go ahead and create some actions and a reducer for a counter.

./src/modules/counter.js

Our incrementAsync and decrementAsync functions return a Thunk. We first dispatch an action and we wrap another function within setTimeout() which dispatches when the timer is up. 🙌

We’ll need to hook up our counter.js to our rootReducer so our store can manage our state.

./src/modules/index.js

To complete our thunk example, let’s update our Home container component to include our Counter state and actions.

./src/containers/home/index.js

Try it out!

The time has come to fire up our React app using yarn start. You can see below our efforts in action! See this live on Heroku.

Our working example 🤘

I’ve more tutorials and videos on YouTube. Subscribe? ❤️