React is an excellent front-end framework, but we can’t say it’s perfect. React, for example, was struggling to deal with state management issues in large projects. Therefore, a lot of technologies have been derived for the problem of state management, such as Flux, Redux and so on. In this article, we only discuss Redux. If you learn Redux, you don’t need to learn Redux, because Redux is an upgrade of Flux. If you use Vue or Angular, you can use Redux, even if you use native JS.

In this article, I will introduce you to React Redux in seven steps. After reading this article, you will know how to use React Redux.

The preparatory work


1. What is state?


2. What is Redux and why redux?


3. What is Reducer?


4. What is store?


5. How to associate store?


6. What is Action?


7. How do I handle asynchronous code?


conclusion


attach

The preparatory work

By default, you know React and ES6 before you start preparing.

First we create the project using the following command line:

npx create-react-app react-redux-exampleCopy the code

If you want to use it in a created project, you should execute the following command:

npm install redux react-reduxCopy the code

Then we need to create some files.

  • 1. Create a container folder in the SRC directory and create a Articles.
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()}return (
    <div>
      <AddArticle saveArticle={saveArticle} />
      {articles.map(article => (
        <Article key={article.id} article={article} />
      ))}
    </div>
  )
}

export default ArticlesCopy the code

  • 2. Create a components folder under SRC and create AddArticle/ addArticle. js and Article/ article.js

Article.js

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

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

export default articleCopy the code

AddArticle.js

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 AddArticleCopy the code

App.js

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

function App() {
  return <Articles />
}
export default AppCopy the code

If you have completed the above steps, you can continue!

1. What is State?

The core of every React component (except stateless components) is state. It determines how the build will be rendered and how it will appear. To really understand State, you have to go through real examples. Such as whether popovers open, whether components are rendered, etc.

// 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"},])Copy the code

Now that you know what state is, let me introduce you to Redux.

2. What is Redux and why is redux used?

Managing state without Redux or some other tool would be extremely difficult. Imagine we have to check each component to see if the popover is open. To solve this problem, we had to pass props between components, which made the component data very messy and the development cost very high. But with Redux, things are much easier.

3. What is Reducer?

Reducer is a pure function that takes the previous state and action as arguments and returns an updated state. Reducer can only handle synchronized code, which means there are no side effects like HTTP requests. We can also use Redux to handle asynchronous code, as we’ll learn later. Of course, if you don’t know about action, it doesn’t matter. We will introduce it later. Let’s create our first Reducer.

As usual, we create a Store folder and then create a reducer.js file.

Reducer. Js file

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 reducerCopy the code

Reducer is a pure function that takes the previous state and action as parameters and returns an updated state. Now that we have created the Reducer, let’s create the Store.

4. What is store?

The Store is where the React project stores state, which you can think of as a large JavaScript object. We need a Reducer as a parameter when we create a store. We have created a reducer, let’s associate it with the store.

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"))Copy the code

5. How to associate store with React?

To associate store with React, we need to introduce a helper function called Provider. The App component is then wrapped around the Provider component, passing the Store as the props value to the Provider.

Index. Js file

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"))Copy the code

Articles. Js file

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()
    // ...
  }
  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)Copy the code

Here we introduce connect(), which helps us connect the component to the store and get state.

We declared a new function called mapStateToProps(), but it could have been anything else, and it took the state value from the store as its argument and returned an object.

To get the state in the store, we need mapStateToProps() as an argument to the connect function.

6. What is Action?

Actions contain various types, such as REMOVE_ARTICLE or ADD_ARTICLE. It is distributed from the React component (passing data) to redux’s store. When an action is just a messenger, it cannot change the store. Store can only be changed by reducer.

To create an action in the project, we first create an actiontypes.js in the Store folder

export const ADD_ARTICLE = "ADD_ARTICLE"Copy the code

Then we go to the Articles. Js file

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)Copy the code

Here we introduce everything from actiontypes.js. Then a new function, mapDispatchToProps, is created that accepts Dispatch as an argument.

Store/reducer. Js file

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 reducerCopy the code

We introduced actionTypes. Then we check the reducer function to see if the action type is ADD_ARTICLE. If so we create an object that returns a new state.

7. How does Redux handle asynchronous code?

We need to create a new file, actionActionine.js

store/actionCreators.js

import * as actionTypes from "./actionTypes"

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

Articles.js

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)Copy the code

Now that we’re not done, we need to introduce a new dependency package, Redux-Thunk, which is middleware that allows us to work with asynchronous code.

npm install redux-thunkCopy the code

Index. Js file

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"))Copy the code

store/actionCreators.js

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)
  }
}Copy the code

Articles.js

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)Copy the code

The only change we’ve made here is to change addArticle to simulateHttpRequest and now we can execute asynchronous code via Redux.

conclusion

When we were dealing with large and medium react projects, managing our state became very difficult. Redux makes it very easy, but there are many other solutions like the Context API (Hook) that are very useful for dealing with state management issues.

Finally, you can pay attention to my article and regularly share front-end knowledge for your friends, hoping to help your friends.

attach

This article refers to the official website of Redux, as well as some good articles on the Internet, if there is infringement, please contact me, thank you.