7 steps to understand React Redux
Tags: react, redux, beginners
Published: 2019-12-27 12:57:08

Originally posted on [my blog](https://www.ibrahima-ndaw.com/blog/7-steps-to-understand-react-redux/) <hr>

React is awesome, we can't say it enough. But where it comes to the state management part, things become tricky. There is so much terminology to retain: state, store, actions, reducers, middleware, etc. With medium size or bigger react apps, managing our state can be really hard as our application grows. We need to manage it either by redux or alternatives like the context API, flux, etc. In this article, we will focus on redux and how it works with React. Redux is a stand-alone library, it's framework agnostic, that's mean you can use it with other frameworks or just vanilla JavaScript.<br>
In this post, I will lead you through 7 steps to understand react-redux in the easiest way.

- [Prerequisite](#prerequisite)
- [1. What is a state?](#1-what-is-a-state)
- [2. What is redux and why we need it?](#2-what-is-redux-and-why-we-need-it)
- [3. What is a reducer?](#3-what-is-a-reducer)
- [4. What is a store?](#4-what-is-a-store)
- [5. How to connect our store to React?](#5-how-to-connect-our-store-to-react)
- [6. What is an action?](#6-what-is-an-action)
- [7. How to handle asynchronous code with redux?](#7-how-to-handle-asynchronous-code-with-redux)
- [Conclusion](#conclusion)
- [Resources](#resources)

## Prerequisite

This post assumes that you have at least a basic to a mid-level understanding of React and ES6. Then, you'll need to create a fresh react app with this command: <br>

```shell
npx create-react-app react-redux-example
```

And add to your react app the `redux` and `react-redux` packages by running in your shell

```shell
npm install redux react-redux
```

Then, we need to create some files. <br>

- Add a `containers` folder in the `src`, then create `Articles.js` file.

```jsx
import React, { useState } from "react"
import Article from "../components/Article/Article"
import AddArticle from "../components/AddArticle/AddArticle"

const Articles = () => {
  const [articles, setArticles] = useState([
    { id: 1, title: "post 1", body: "Quisque cursus, metus vitae pharetra" },
    { id: 2, title: "post 2", body: "Quisque cursus, metus vitae pharetra" },
  ])
  const saveArticle = e => {
    e.preventDefault()
    // the logic will be updated later
  }

  return (
    <div>
      <AddArticle saveArticle={saveArticle} />
      {articles.map(article => (
        <Article key={article.id} article={article} />
      ))}
    </div>
  )
}

export default Articles
```

- Add a `components` folder in the `src`, then create `AddArticle/AddArticle.js` and `Article/Article.js`.<br>
- In the `Article.js`

```jsx
import React from "react"
import "./Article.css"

const article = ({ article }) => (
  <div className="article">
    <h1>{article.title}</h1>
    <p>{article.body}</p>
  </div>
)

export default article
```

- In the `AddArticle.js`

```jsx
import React, { useState } from "react"
import "./AddArticle.css"

const AddArticle = ({ saveArticle }) => {
  const [article, setArticle] = useState()

  const handleArticleData = e => {
    setArticle({
      ...article,
      [e.target.id]: e.target.value,
    })
  }
  const addNewArticle = e => {
    e.preventDefault()
    saveArticle(article)
  }

  return (
    <form onSubmit={addNewArticle} className="add-article">
      <input
        type="text"
        id="title"
        placeholder="Title"
        onChange={handleArticleData}
      />
      <input
        type="text"
        id="body"
        placeholder="Body"
        onChange={handleArticleData}
      />
      <button>Add article</button>
    </form>
  )
}
export default AddArticle
```

- In the `App.js`

```jsx
import React from "react"
import Articles from "./containers/Articles"

function App() {
  return <Articles />
}
export default App
```

_So, if you've done with the prerequisite, we can move on and demystify what is a state._

## 1. What is a state?

The heart of every react stateful component is its state. It determines how the component should render or behave. To really understand the state, we must apply it to real examples. Is the user authenticated? is a state that controls if a user is authenticated or not, is modal open? is also a state which looks if a given modal is open or not the same as a list of articles or a counter etc.

```jsx
// Class based component
state = {
  articles: [
    { id: 1, title: "post 1", body: "Quisque cursus, metus vitae pharetra" },
    { id: 2, title: "post 2", body: "Quisque cursus, metus vitae pharetra" },
  ],
}
// React hooks
const [articles, setArticles] = useState([
  { id: 1, title: "post 1", body: "Quisque cursus, metus vitae pharetra" },
  { id: 2, title: "post 2", body: "Quisque cursus, metus vitae pharetra" },
])
```

_Now we know what is a state, it's time to introduce redux and dive deeper into it._

## 2. What is redux and why we need it?

Managing our state without redux or alternatives can be tough. Imagine we have to check on every component if the user is authenticated or not. To handle that use-case, we have to pass props through every component and following the application growth, it's just impossible to manage our state like that. And there is where redux really shines.<br>
Redux is an independent library that helps us manage our state by giving access to our components the state it needs via a central store. Redux stores the whole state of our app in an immutable object tree.<br>
_Another broad term: store, to understand it well we first need to explain what is a reducer?_

## 3. What is a reducer?

A reducer is a pure function that receives the old (previous) state and an action as arguments, then returns as output the updated state. The reducer handles only synchronous code, that's mean no side effect like HTTP request or anything like that. We can still handle asynchronous code with redux and we'll learn how to do it later. By the way, if you get confused by the term action, no worries, it will be much clearer later. So, Let's create our very first reducer.<br>
The structure of your files is totally up to you, however, I'll follow the convention and create a `store` folder in the project to hold our reducers, actions, etc. Then, create a `reducer.js` file.

- In `reducer.js`

```jsx
const initialState = {
  articles: [
    { id: 1, title: "post 1", body: "Quisque cursus, metus vitae pharetra" },
    { id: 2, title: "post 2", body: "Quisque cursus, metus vitae pharetra" },
  ],
}

const reducer = (state = initialState, action) => {
  return state
}
export default reducer
```

As I said earlier, a reducer is just a function that receives the previous state and an action as parameters and returns the updated state. Here, we have not a previous state, so it will be undefined, therefore we need to initialize it with `initialState` which hold our predefined articles.<br>
_Now we've set up our reducer, it's time to create our store_

## 4. What is a store?

A store holds the whole state tree of our react app. It's where our application state live. You can see it as a big JavaScript object. To create a store we need a reducer to pass as an argument. We already have a reducer, let's connect it to our store.

- In our `index.js` file.

```jsx
import React from "react"
import ReactDOM from "react-dom"
import { createStore } from "redux"

import "./index.css"
import App from "./App"
import reducer from "./store/reducer"

const store = createStore(reducer)

ReactDOM.render(<App />, document.getElementById("root"))
```

To create a store, we first need to import `createStore` from the redux package, then import our reducer and finally pass it as an argument to the store `createStore(reducer)`. With that, we successfully create our store, but we've not done yet, we have to connect it to our react app.

## 5. How to connect our store to React?

To connect the store to react, we need to import a helper function named `Provider` from the react-redux package. Then wrap our `App` component with `Provider` and pass as props the `store` which has as value our current store.

- In our `index.js` file.

```jsx
import React from "react"
import ReactDOM from "react-dom"
import { createStore } from "redux"
import { Provider } from "react-redux"

import "./index.css"
import App from "./App"
import reducer from "./store/reducer"

const store = createStore(reducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
)
```

Then, we need to connect our component to the redux store.

- In `Articles.js`

```jsx
import React from "react"
import { connect } from "react-redux"

import Article from "../components/Article/Article"
import AddArticle from "../components/AddArticle/AddArticle"

const Articles = ({ articles }) => {
  const saveArticle = e => {
    e.preventDefault()
    // the logic will be updated later
  }
  return (
    <div>
      <AddArticle saveArticle={saveArticle} />
      {articles.map(article => (
        <Article key={article.id} article={article} />
      ))}
    </div>
  )
}

const mapStateToProps = state => {
  return {
    articles: state.articles,
  }
}

export default connect(mapStateToProps)(Articles)
```

Here, we first import `connect()`, a function that returns a higher-order function and receive as input a component. It helps us to connect our component to the store and give access to get the state.<br>
Then, we declare a new function named `mapStateToProps()` (you can name it whatever you like). It's used to get our state from the redux store. The function receives as parameter the `state` stored in redux and returns a JavaScript object that will hold our `articles`.<br>
And to reach the store, we need to pass `mapStateToProps()` to the `connect` function. It will take our component `Articles` and return a wrapper component with the props it injects. That means we can now get our state from the store. The state is received by the component through props, we can still show the `articles` as before but now through redux.<br>
_We've successfully connected our store to react and get our state from it. Now, let's dive into actions_

## 6. What is action?

An action is a payload of information that contains a type like `REMOVE_ARTICLE` or `ADD_ARTICLE` etc. Actions are dispatched from your component. It sends data from your react component to your redux store. The action does not reach the store, it's just the messenger. The store is changed by reducer.<br>
To create an action in our project, we need to create in our `store` folder a new file named `actionTypes.js`.

```jsx
export const ADD_ARTICLE = "ADD_ARTICLE"
```

Then, we need to go to our `Articles.js` file and add the following code.

```jsx
import React from "react"
import { connect } from "react-redux"

import Article from "../components/Article/Article"
import AddArticle from "../components/AddArticle/AddArticle"
import * as actionTypes from "../store/actionTypes"

const Articles = ({ articles, saveArticle }) => (
  <div>
    <AddArticle saveArticle={saveArticle} />
    {articles.map(article => (
      <Article key={article.id} article={article} />
    ))}
  </div>
)

const mapStateToProps = state => {
  return {
    articles: state.articles,
  }
}

const mapDispatchToProps = dispatch => {
  return {
    saveArticle: article =>
      dispatch({ type: actionTypes.ADD_ARTICLE, articleData: { article } }),
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Articles)
```

Then, we need to import everything from `actionTypes.js`. And create a new function `mapDispatchToProps` which receive a function `dispatch` as parameter. The `mapDispatchToProps` return an object which has a property `saveArticle`. It's a reference to a function that will dispatch an action in our store.<br> `saveArticle` holds an anonymous function that receives our `article` as an argument and returns the `dispatch` function. It receives the type and the data to update as parameters. And as you guess, it will dispatch the action in our store.<br>Finally, we need to pass `mapDispatchToProps` as second argument to the `connect` function. And to make it work, we need to update our reducer and add the action `ADD_ARTICLE`.

- In `store/reducer.js`

```jsx
import * as actionTypes from "./actionTypes"

const initialState = {
  articles: [
    { id: 1, title: "post 1", body: "Quisque cursus, metus vitae pharetra" },
    { id: 2, title: "post 2", body: "Quisque cursus, metus vitae pharetra" },
  ],
}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.ADD_ARTICLE:
      const newArticle = {
        id: Math.random(), // not really unique but it's just an example
        title: action.article.title,
        body: action.article.body,
      }
      return {
        ...state,
        articles: state.articles.concat(newArticle),
      }
  }
  return state
}
export default reducer
```

As you can see, we import our `actionTypes`. Then, we check in our `reducer` function if the action's type is equal to `ADD_ARTICLE`. If it's the case, first create a new object which holds our article then append it to our articles array. Before we return the state, we copy the old state, then `concat` it with the new article. In that way, we keep our state safe and immutable.

## 7. How to handle asynchronous code with redux?

The reducer as I say earlier handles only synchronous code. To execute the asynchronous code, we need to use an action creator. It's a function that returns a function or an action I should say. So, to use it in our project, we need to create a new file `actionCreators.js`.

- In `store/actionCreators.js`

```jsx
import * as actionTypes from "./actionTypes"

export const addArticle = article => {
  return {
    type: actionTypes.ADD_ARTICLE,
    article,
  }
}
```

Here, we declare a new action creator named `addArticle`. It's a function that receives the `article` as an argument and returns the type of the action and the value. By the way, `article` is the same as `article: article`, it's just an ES6 convenient syntax. Now we can move on and change the function `mapDispatchToProps` in the `Articles.js` file.

- In `Articles.js`

```jsx
import React from "react"
import { connect } from "react-redux"

import Article from "../components/Article/Article"
import AddArticle from "../components/AddArticle/AddArticle"
import { addArticle } from "../store/actionCreators"

const Articles = ({ articles, saveArticle }) => (
  <div>
    <AddArticle saveArticle={saveArticle} />
    {articles.map(article => (
      <Article key={article.id} article={article} />
    ))}
  </div>
)

const mapStateToProps = state => {
  return {
    articles: state.articles,
  }
}

const mapDispatchToProps = dispatch => {
  return {
    saveArticle: article => dispatch(addArticle(article)),
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Articles)
```

As you can see, we first import our action creator `addArticle`, then in the `mapDispatchToProps` function, we update the argument passed to `dispatch`. Now, it receives the action creator and its value `article`.<br>
But we've not done yet, we need to add a new package `redux-thunk` to our project to be able to handle asynchronous code.

```shell
npm install redux-thunk
```

`redux-thunk` is a middleware that will help us handle the asynchronous code. Middleware provides a way to interact with actions that have been dispatched to the store before they reach the reducer. Now let's implement it to our project.

- In `index.js`

```jsx
import React from "react"
import ReactDOM from "react-dom"
import { createStore, applyMiddleware } from "redux"
import { Provider } from "react-redux"
import thunk from "redux-thunk"

import "./index.css"
import App from "./App"
import reducer from "./store/reducer"

const store = createStore(reducer, applyMiddleware(thunk))

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
)
```

In this code block, we first import `applyMiddleware` from redux and `thunk` from redux-thunk. Then to make it work, we need to pass to `createStore` a second argument or enhancer which receives our middleware `thunk`. By doing this, we are now able to deal with asynchronous code. Let's now update our action creator.

- In `store/actionCreators.js`

```jsx
import * as actionTypes from "./actionTypes"

export const addArticle = article => {
  return {
    type: actionTypes.ADD_ARTICLE,
    article,
  }
}

export const simulateHttpRequest = article => {
  return dispatch => {
    setTimeout(() => {
      dispatch(addArticle(article))
    }, 3000)
  }
}
```

For this post, we will just simulate an HTTP request.<br>
Here, we have a new action creator `simulateHttpRequest` which receives the `article` as input and return a function. Due to the `thunk` middleware, we can access to `dispatch` because our middleware runs between the dispatching of our action and the point of time the action reaches the reducer. Therefore, we can get `dispatch` as an argument. Then, wait 3 seconds with `setTimeout` to just simulate an HTTP request before dispatching the action and add the article to our array of articles.<br>
We've changed our action creators a little bit, to make it work again, we need to update `Articles.js`.

- In `Articles.js`

```jsx
import React from "react"
import { connect } from "react-redux"

import Article from "../components/Article/Article"
import AddArticle from "../components/AddArticle/AddArticle"
import { simulateHttpRequest } from "../store/actionCreators"

const Articles = ({ articles, saveArticle }) => (
  <div>
    <AddArticle saveArticle={saveArticle} />
    {articles.map(article => (
      <Article key={article.id} article={article} />
    ))}
  </div>
)

const mapStateToProps = state => {
  return {
    articles: state.articles,
  }
}

const mapDispatchToProps = dispatch => {
  return {
    saveArticle: article => dispatch(simulateHttpRequest(article)),
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Articles)
```

Here, the only thing we have to do is change `addArticle` to `simulateHttpRequest`, in that way, everything should work again, and now we're able to handle asynchronous code through redux.<br>

You can find the finished project [here](https://github.com/ibrahima92/react-redux-example) <br>

## Conclusion

When it comes to dealing with medium size to bigger react apps, managing our state can be really hard. And a package like redux can make it very easy. There are also some alternatives like the context API (+hooks) which is very helpful and does not require a third-party library, but dive into redux is still relevant.<br>
However, redux is overkill for simple React app like our project, we don't need redux to manage our state, but it's easier to understand how redux works with a very simple app.

| [TWITTER](https://twitter.com/ibrahima92_) | [BLOG](https://www.ibrahima-ndaw.com/) | [NEWSLETTER](https://ibrahima-ndaw.us5.list-manage.com/subscribe?u=8dedf5d07c7326802dd81a866&id=5d7bcd5b75) | [GITHUB](https://github.com/ibrahima92) | [LINKEDIN](https://www.linkedin.com/in/ibrahima-ndaw/) | [CODEPEN](https://codepen.io/ibrahima92) | [DEV](https://dev.to/ibrahima92) |
| -------------- | ------------------------------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------ | ---------------------------------------- | -------------------------------- |

## Resources

[React Redux official documentation](https://react-redux.js.org/introduction/quick-start)
[Redux devtools](https://github.com/reduxjs/redux-devtools)
[Redux Best practices](https://github.com/markerikson/react-redux-links/blob/master/redux-architecture.md)
[Redux saga](https://redux-saga.js.org/)
[The Context API](https://reactjs.org/docs/context.html)