Wiring Up a Redux Store in React Apps
By: Marco Lancellotti
Tags: Reactjs, Redux Thunk, React, Redux

The Redux Store is modified by using the Actions flow

Keeping in mind what we have just sais, let’s see how we integrate the Redux pattern inside a React Application.

Redux in React

The first thing I want to point out, is that when we talk about Redux in React we basically talk about the React-Redux library.

It is this library that allows Redux and React to communicate with each other properly and makes it easier for us to read the store data or dispatch our functions.

As stated in the introduction, we are not going to use the ReduxToolkit for this article, so assuming we created our app with create-react-app and no particular template, we must install the Redux library and the React-Redux library manually:

npm install --save redux react-redux

1- Defining reducer and action creators

Before we actually use any function from the redux or react-redux library we will have to create our action creators and reducers. I usually structure my projects in order to have a reducers and actions folders where I define all my functions separated by topic and then barrel them into a single index.js file to be exported.

2- Combining reducers

Most importantly, make sure that inside reducer/index.js file you combine all your reducers with redux’s combineReducers function:

We want to export all the reducer combined, in order to transform them into the Redux Store.

Keep in mind that the key you provide inside the combineReducers argument, will be used as a prop inside the Redux Store.

3 - Creating the State and wiring up the Provider

We must make sure to create a Redux Store out of our combined reducers and provide it throught our application.

To create the store, all we have to do is to import our combined reducers and call the createStore function provided by the Redux library.

To make the store available to all our components, we will make use of the Provider component of the React-Redux library. This component expects a store as a props and it is intended to wrap our entire application, namely, our <App /> component!

Once we have wrapped our main component inside the provider, all our nested components will be able to get access to our state data!

Accessing the store

We have said we are now able to reach our state from all the components in our app but we must see how. There are actually 2 different methods to read the data from the store: the connect function and the useSelector hooks.

Option 1: Connect & mapStateToProps functions.

The most traditional way to get access to the store data from one of our components, is to pass the entire component to the connect function from react-redux.

The connect function will return a copy of the component entirely connected to the store. However, in order for the component to properly read the store data, we must first provide an important argument to the connect function: mapStateToProps.

mapStateToProps is a function used for selecting the part of the data from the store that the connected component needs. This function should be passed as the first argument to connect , and will be called every time when the Redux store state changes.

mapStateToProps is called with the entire store as its first and only argument and should return an object where all the keys represent the mapped props from the store, to be consumed in the reducer. Let’s try to make an example:

If we want to read our list of items from our store inside of a MyList component, this is what we would do:

Note how the object returned by mapStateToProps is defining the name of the props the component will use to access the data.

An important aspect is that the connect function can be used for both class and functional components.

Option 2: useSelector (functional components only)

In the last version of React-Redux, hooks are available for us to use inside our functional components.

In order to read data from the Redux Store, we may use the useSelector hook. The useSelector hook is conceptually corresponding to mapStateToProps but it has some differences, the most important being:

It can be used only inside functional components.

It can return any value, not necessarily an object.

not necessarily an object. It can be declared multiple times inside the component.

inside the component. It is called every time the components re-render but only if its returned value has changed.

Its use is however very similar to mapStateToProps, since its mandatory first argument is a function that receives the entire store, just as in mapStateToProps , with the difference, as already said that it can return any value. Let’s see the same example with useSelector:

Dispatching the actions and modifying the store

Now that we have seen how to read data from our store, let’s focus on how we can perform changes on it, that is, how to dispatch our action creators!

If you have understood how Redux works, it will be clear to you that in order to trigger an action and send it to all the reducer in the store, what we need is to pass an action creator to the store.dispatch() function.

But how can we access the dispatch function from a component? Well, here is where the React-Redux magic comes into place and again, we have 2 different ways!

Option 1: Connect & mapDispatchToProps

Very similarly to what we have seen with mapStateToProps, the connect function allows us to map also the actions creators to the component’s props.

The trick is very simple: connect can accept a second parameter called, guess what? mapDispatchToProps.

mapDispatchToProps needs to be an object whose keys will be mapped to a prop inside a component. Each key of this object must be a function that eventually returns an action, that is, an object with type (mandatory) and payload (optional) arguments.

Let’s see a very simple example, extending the previous MyList.js component. We will import our previously declared removeItem action creator from its file, and map it to a delete property inside the component. We will then add a button for each item of the list, and try to call our delete property with the id of the item as its argument:

IMPORTANT NOTE: in some cases we only want to use action creators inside a component, regardless of the rest of the store. In those cases, you should provide null as the first argument to connect and mapDispatchToProps as a second argument!

Option 2: useDispatch (functional components only)

An even simpler approach is available to us inside of functional components, thanks to the useDispatch hook.

This hook provides a direct reference to the store.dispatch() function, making its use really straightforward.

Of course, you only need to call the hook once inside a single component and then use its reference with different action creators.

Let’s see how our example MyList looks with this approach:

Handling async actions with Redux-Thunk

There we go, my friends! We have our store in place now, but we need to handle a little issue that we may have if we need to consume some API inside our actions creators.

The problem

Remember: action creators are supposed to return a plain object. But when we make use of asynchronous code, we are breaking this rule and Redux is going to show a very big error screen to us:

If we perform an async call inside an action creator, this is what we run into.

The solution

In order to bypass this issue, we will make use of a middleware called Redux Thunk.

What Redux thunk does, is putting itself in the middle every time an action creator is called and performs a check on what is returned; if the return value is an object, it will then call store.dispatch for us.

If the return value is a function, it will prevent redux from breaking and instead will provide a new functions with 2 arguments out of the box:

the dispatch function, that we can use to dispatch the action once we performed all our async code or other logics

function, that we can use to dispatch the action once we performed all our async code or other logics a getReduxStore function, that we can use to inspect the whole content of the store!

Let’s see how to implement this. We can install it with

npm i --save redux-thunk

We can now move to our index.js file and import thunk from redux thunk and applyMiddleware from the redux library.

All that remains to wire up Redux-Thunk is to pass thunk as the first argument to applyMiddleware and applyMiddleware as the second argument to createStore . From now on, all our actions will be handled by the thunk middleware.