Integrating Redux With a Finished React App

Matthew Jones
8 min readApr 11, 2021

If you’re anything like me, you may have found yourself suddenly thinking about integrating Redux functionality to manage state in your already finished React application.

Why Redux?

Adding a new framework to an application that you’ve already built in full is a daunting proposition. I know that I needed some convincing before I was willing to take the plunge and rebuild my state from the ground up.

Redux does offer a lot, however. Specifically, it makes managing the state of your application both easier and cleaner. Depending on the size of your application, you may have already run into the problem of having to send state around between parent and child components as props so much that it starts to be clunky and confusing. Imagine, for example, that you are working on a social media application in which each user has a profile. Looking at many different existing social media platforms, it seems likely that your user’s profile picture will be displayed in multiple places on each page that they visit.

Look at the image above, just at the top of this user’s page, we can already see this user’s profile picture featured in three different places, and what’s more, some of those places are in different elements that we would render using different components. Each of those components will all need access to the same state, so we can already see how this can quickly get out of hand if we simply try to pass in state as props for each component all the way down. What happens if one child component doesn’t need that state, but a one of its children does? We can end up in a situation where components are passed state that they don’t even need just because they need to pass it down to a later component that does need it.

This can get very messy very fast, and is not a very clean way to write our code. Redux helps us solve this problem.

How does Redux work?

Redux keeps all of our state in one central location, called a store, so that we can easily access it from anywhere in our application.

This eliminates the need for multiple components to carry state that they don’t need.

Before we can go on, we need to install redux and react-redux. This is the same as installing any other package using yarn or npm. Since I use npm, it’s a simple matter of running npm install react and npm install react-redux.

Now that we know what the store is and how it works, we need to talk about the other components of Redux, the first of which is the reducer.

Reducers

The reducer is the function that we use to manipulate our store and change the state of our application.

Here, the function countReducer is the reducer for our function. Every reducer takes in two arguments, a state and an action. The state is the current state of your application (here you can see that we are also passing in a default state of zero). The action is the call that is being made which we will use to change the state in our store. We process actions using a switch statement. If you’re not already familiar with switch statements, they are very similar to if statements. You can read more on them here.

In the example above, we are using two actions, one to increment the state and the other to decrement it. Those actions add and subtract one from the state respectively. This is all that the reducer does, take in the current state, perform some sort of change on it based on the action passed in to it, and then return the new state.

Actions

So you’ll notice that we’re using actions to change our state in the above example. The good news for you is that Redux actions are a lot simpler than they may seem at first — really, they’re just JavaScript objects!

Each one has two properties: a type and a payload. The action type is what we see referenced in the reducer from our previous example. There, it was looking for two different possible types of action, ‘increment’ and ‘decrement’. Here, the type is ADD_ARTICLE. The second property is the payload. Here, the payload is another JavaScript object containing a title and an id for a new article. In general, the payload is the information you provide to your reducer containing all that it needs to know in order to perform the desired change to the state. In this case, your reducer action might look something like this:

Here, your reducer takes the action payload and uses the .concat function to add it on the end of your articles array in the state. For applications with sufficiently small state, your actions can be coded in the same file as your reducer.

Now What?

Now we know how to create a reducer and how to use actions to change the state. All that’s left is to connect our store to the rest of our application and allow our components to use those actions to change the state.

In order to do this, what we need to do is use a new piece of functionality that redux offers us called the Provider.

This is done in our src/index.js file. This is what mine looks like in the most recent project that I finished:

There are a few different things going on here. First, we need to actually create our store. I chose to do that in a separate file and then import it, but you could do that inside of index.js as well if you wanted to. Here’s my store:

It really is as simple as that. We need to import our reducer as well as the createStore function from redux, and then we simply define a const named store and set that equal to the result of createStore when we pass our reducer in as the sole argument.

Once you’ve set up your store, wherever you decide to do that, it’s time to set up your provider. What provider does is allow access to the store from any components wrapped inside it. What we’re going to do in this case is wrap our highest level component, app, inside of it, and then everything else in our application will inherit it from there. To do this, all we have to do is import Provider from react-redux and then edit our index.js file to wrap our app inside of it. Right now, yours is likely wrapped in React.strictmode, but we can get rid of that. When we do create our provider, it’s important that we pass in our store as a prop. There! We’re almost done.

The Home Stretch

The last thing that we need to do is give our components the ability to read and write state. To do this, we will make use of the last pieces of redux functionality that we’re going to cover today — mapping our state and actions to props and using the connect function.

Here, you see mapStateToProps being used in a simple context. It’s a function that will take in state as an argument and return an object as a prop of the component. By placing this inside one of our components, we have now given it access to our array of articles in our state. We can access this like we would access any other prop, this.props.articles if we are using class based components or simply props.articles if we are using functional components.

If you were to console.log(this.props.articles), you would see a list of all of our articles that we keep in our state.

But what about adding new things to the state? For this, we use another, very similar function: mapDispatchToProps.

The important thing to know about this one is that the arguments for dispatch are the name of the redux action that you wish to perform, and the payload that you want to use. The prop that you assign them to can have any name, but for the sake of readability I would strongly advise that you use the same name as your redux action.

You can use the new dispatch that you have just passed in as a prop the same way that you would use any other functions as props.

The last thing for us to do now is to put it all together using connect. The first thing to do is to import connect from react-redux at the top of your component. This is also necessary to use the mapStateToProps and mapDispatchToProps functions. After you have imported connect and brought in the state and actions that you want your component to have, all that you have to do is include one final line at the bottom of your component

Instead of simply exporting your component, in this case KnightsList, you have to export a connected component that now has access to the store. If you have a component that you only want mapDispatchToProps in, you do have to pass in null for the other argument as connect requires an argument for mapStateToProps. However, it is possible to use connect without an argument for mapDispatchToProps.

Ta-Da!

And that’s really all there is to it! You can now go through your components and replace any instances of setting state with the appropriate dispatch actions and any instances of reading state with the appropriate state-containing prop.

Conclusion

Although it may sound quite challenging, adding Redux to a completed application is actually very simple. There is some prep work that you have to do — setting up the reducer and your actions, but after that it’s a simple matter of connecting your app to the store and then making a one-for-one replacement of each reference to state. I hope that you learned something from this guide. Continue to play with Redux and learn, it’s a very powerful tool and something that you will be glad to have in your programming arsenal.

Thanks for reading and stay tuned on this blog!

--

--

Matthew Jones

Matthew Jones is a full stack developer who enjoys coding, drinking tea, and playing board games with his friends.