Another React-Redux guide

I personally had a hard time trying to understand the idea of why I needed Redux and how it exactly would benefit my React project back in my Web Development bootcamp. I went through a lot of explanations in my course, but at the end of the day, I was still confused as to how use Redux.

When I finally got the point of using React and Redux, I have decided to share of my knowledge and hopefully to make it easier for you to go through this material.

Let’s get started.

First try not to think of the ways that React and Redux are somehow related. They are totally separate.

Imagine the React part as a view layer and the Redux part as a data layer. I know it’s not that simple right away to get the idea of what is a data layer and what exactly is a view layer. On the diagram below I’m going to show and give an explanation about both.

So, the diagram above basically shows in general two different pieces React (view), Redux (data), React/Redux (App) that going to be connected on some point.

Let’s get into Redux in more details.

Redux would be the state that holds the data of our app. Container, it is basically a component hooked to redux. Using redux state inside the react component upgrade this component to a container.

Basically, you can think of Redux as collection of all centralize data of our app which refer to as a state.

React would be something that’s displayed on the screen and a user will be interacting with.

In the diagram above App will be the meet point of React and Redux.

Reducer.

When I think of Redux it starts with a deep understanding of what Reducer is and how exactly I can manipulate with my data.

Reducer is a function that returns a piece of application state.

At first I was confused trying to get the idea of where exactly my state goes whenever it get returned.

So here I’ll try to bring my own way on how the data flows between different parts inside of application, to explain how it starts inside the reducer and goes on.

Diagram that shows data flow.

Below you can see what basically happens inside the reducer. I have data about dogs. As you can see the whole thing is what’s called application state. Inside this state I have 2 reducers.

Dogs, selectedDog will be the key of each reducer. Information about breed will be the value that we have to assign to our key.

To move forward let’s look at the simple reducer. Basically, a function that returns data about our dog’s breeds. To see how data flows from our reducer to other parts of our application such as components, actions and so on, we have to wire it up. For this purpose, all I need is to export our reducer. This way I can go ahead and import it somewhere else inside application.

In the diagram below you can see how to bring in my reducer into combineReducers file called index.js that locates inside general reducers folder. So, in our example I would have a folder (reducers) that contain of index.js file (combineReducers) and reducer (reducer_dogs.js). Your goal for now is to focus how do I bring in my reducer into combineReducers file.

So, in this case our application has a single piece of state called dogs and the value returns whatever we have in our DogsReducer function.

Now if you recall we are going to move forward to our next part from the general diagram above which is the component part. So basically, the purpose of creating our component will be to render what we have inside of our reducer.

Let’s start exploring the diagram above.

First, I’m going to promote our component to container. Container has direct access to our state, produced by Redux. Just a reminder, our state sits inside of reducer (list of breeds). Connection between container and our state we will be doing with ‘react-redux’ library. You can see on top we import connect from ‘react-redux’. Remember the goal is to bring our state (list of breeds) to show up inside of our container.

So, inside of our container I’m going to create a list of our breeds, the provider here is: this.props.dogs which basically comes from our state. For this matter we use {this.renderList()}. So right above I must define a new function called renderList. Inside of this function we going to wire up our list of breeds from reducer. We have an array of breeds, so what we going to do is map over each element (breed) of this array and return it as a dog breed.

So here we come to this interesting part which called mapStateToProps. So, imagine that when you have a reducer inside of state, in our example it is a list of breeds and you trying to wire this list up inside of container, you have to bring this list over to container, only this way container will be aware of something that sits in reducer. mapStateToProps is this guy who brings our reducer’s data from state to container.

Connect(mapStateToProps)(DogList) is basically a way of putting together reducer and component. So it is important to understand what gets returned by mapStateToProps function is basically what we will have in our this.props inside of renderList function.

In our app.js file all we need is to import our DogList container in order to render it.


Actions.

We can change our state by using action and action creators. Action creators is how we create our actions, actions flow through all of our reducers. Action creator is just a function. Remember when we were dealing with connecting between our state and a component DogList, we used :

Before we create our first action creator lets go through some important points in our container.

To be able to connect our container with our action we going to import one more thing:

Our action creator will be creating an action that will flow towards our reducers, for this purpose we are using our bindActionCreators.

Now let’s see what we are going to use in order to send our action toward our reducer.

Whenever bindActionCreators gets called, the result of it (selectDog) will flow to all the reducers using dispatch.

Again, the purpose of dispatch is to take our actions and provide the data to reducer.

Now let’s talk about mapDispatchToProps function. Anything returned from this function will be as props to our container (DogList). You can imagine selectDog as a this.props.selectDog. Same way as when we had to connect our reducer with container using mapStateToProps, so absolutely the same way we going to connect our action and container using mapDispatchToProps.

When we export all of our connections, you can see that basically we only have parts that we have been using to connect between our reducer (mapStateToProps), action (mapDispatchToProps) and container (DogList).

Let’s see now how looks our action creator that returns an action:

Every action must have a type that describe the purpose of this action. Payload is a piece of data that basically describes in more details our action.

Now we are going to create our activeDog reducer.

All reducers get two arguments current state and action. In case where nothing yet selected our reducer will return undefined (return state). Redux does not allow us to return undefined, that’s why error will be thrown. We always have to return non-undefined values.

We can fix this problem of undefined error by using null.

Now instead of having undefined, if nothing selected our value will be equal to null.

When we have our reducer setup, we then have to go and add our new reducer to combine reducers folder.

This is basically how our DogList container looks like finally.

Last piece is we can create one more container to show basically our details of selectedDog container.


So, let’s get started to build our last part😊

First, will add two more lines to our app.js file:

The only changes were made are import DogDetail container that will discuss later on and adding its name to our render method DogDetail.

Then let’s create our DogDetail container, just a reminder we use absolutely the same pattern to build our container.

Now let’s modify our DogDetail container by adding a few more details:

So here we modify our return statement, now please pay close attention to this.props.dog.breed

When we will try to see our container in browser it will throw an error, and the reason is:

Remember last time in our reducer we had state = null because we didn’t want to have an undefined value or in other words we didn’t want to see error shown up. Now I’m saying pay close attention because we have to change now our state = null inside the reducer in order to run properly our DogDetail container. Inside of our DogDetail this.props.dog now equal to null, because it has been defined in our reducer.

So, to avoid this error we now have if statement in our DogDetail container, please see diagram above. This if statement help us to not have error show up because of state = null inside of reducer.


So, the key points that I want you take away with this explanation of working with Redux are:

Redux is in charge of application state.

Application state is formed by reducers.

Reducers are in charge of changing our app state, for this matter they use actions.

Action will always have a type other property are optional.