introduces

In this blog post, we will use the library as an example of how to use Redux in the React project. If you haven’t read my previous blog, here’s a library example:

There are a lot of books in a library, the library has a librarian, if we want to find a book, we can ask the librarian the specific location of the book, convenient for us to get the book quickly; When we want to borrow or return a book, we can give the book to the librarian and show our library card, so that the librarian can help us register the book accurately and put the returned book in the correct place.

From previous blogs, we know the following correspondence:

  • Store: the entire library
  • State: corresponds to the specific State of the library at a certain time. So in this case, let’s say that State is the record of the books that are in the library at that point in time and the books that have been checked out.
  • Action: corresponds to the requests of library users, such as the request for finding books, borrowing books and returning books, etc.
  • Reducer: The Reducer is the library administrator. We send out the request to borrow books, but we don’t know how to register, how to modify the corresponding data of the library. So we left it up to the librarian to process the requests.

Now that you understand the correspondence between the Redux element and the library instance, let’s start writing the actual code for this instance.

The specific code for the library instance

1. Initialize the library State

We use Redux because Redux is used to manage the data in the project, and the data generally has an initial value, which in a real project is usually retrieved from the database through the API.

For the library, there must be an initial value, such as the initial state of the library in the library books and books have been lent records. So the first step, we need to initialize the library data, that is, initialize State. Create a new initstate.js file as follows:

/ / initState. Js file
const initState = {
    // All the books in the library are in the current state
    allBooks: ["Things about the Ming Dynasty"."One Hundred Years of Solitude"."Grave Robbery Notes.".A Dream of Red Mansions.Journey to the West.Romance of The Three Kingdoms].// The library has borrowed books in the current state
    outBooks: {	
        "20152008": ["Forensic clarity.".Journey to the West]."20152023": ["Hello old times.".The Great Qin Empire]."20152135": ["Water Margin"."Collected Works of Lu Xun"]}}// Since we defined the variable in a separate file, we need to export the variable
// Then import the variable in any other file that needs it
export default initState;
Copy the code

2. Define Reducer and process data of accepted actions

Now that the library’s library information has been defined, it’s time to hire another librarian to manage the library information. That is, define a Reducer and modify the State according to the received actions.

His job is to accept requests from library users, such as finding, borrowing and returning books. According to different request information, the library data is processed, and then the library information after processing is returned.

For example, the user 20152135 wants to borrow a book “Things about The Ming Dynasty”, he will send a request to the administrator, the administrator will accept this request, from the library books, “Things about the Ming Dynasty” will be deleted, colleagues will add “Things about the Ming Dynasty” to the user 20152135 lending information. Then return to the latest state of the library books after processing, convenient for the next search and borrowing.

The request sent by the user corresponds to an object in the code. The object of the above book borrowing request is as follows:

const action_2 = {
    type: 'borrow_book'.title: 'Those things in the Ming Dynasty'.userId: '20152135'
};
Copy the code

Now that we have received the request from the user, we need to define a concrete Reducer to handle this request. Create a reducer. Js file and define the code as follows:

/ / reducer. Js file

// The State of the library will be changed
import initState from './initState.js'

function reducer(state = initState, action) {
    Borrow_book borrow_book
    if(action.type === 'borrow_book') {
        let bookIndex = state.allBooks.indexof(action.title);
        state.allBooks.splice(bookIndex, 1);
        state.outBooks[action.userId].push(action.title);
        return state;
    }

    return state;
}

export default reducer;
Copy the code

From the above code, we can see that Reducer is a pure function. In this function, only State is modified without any other side effects. Moreover, as long as the same input, must get the same output.

Here we define only one logic to handle actions. If you want to define more than one logic to handle actions, you can add it directly to this function. For example:

import initState from './initState.js'

function reducer(state = initState, action) {
    if(action.type === 'borrow_book') {
        / /... Modify the logic code for State
        return state;
    }
    if(action.type === 'return_book') {
        / /... Modify the logic code for State
        return state;
    }
    if(action.type === 'search_book') {
        / /... Modify the logic code for State
        return state;
    }

    return state;
}

export default reducer;
Copy the code

3. Define Store and start normal operation of library

The library information is available, the librarian has it, and now we can start the normal operation of the library.

As mentioned above, the library corresponds to Redux’s Store, so what we need to do is to create a Store based on Redux. The definition is very simple, create a new store.js file, the code is as follows:

/ / Store. Js file
import { createStore } from 'redux'     // Introduce the create function in the redux package
import reducer from './reducer'     	// Import the reducer definition

const store = createStore(reducer)

export default store;
Copy the code

4. Introduce Store and render pages using data from Redux

So far, we have successfully created a Store, and now we can introduce a Store in the React component and start managing our data using Redux. Here’s a small example: render a page from data in Redux. Write code directly in the app.jsx file.

import React from 'react';
import store from './Store.js'

class App extends React.Component {
    constructor(props) {
        super(props);
        // Use the getState() function to get the State of the Store at that time
        this.state = store.getState();  
    }
    render() {
        return (
            <div>
                <p>Library in library Books:</p>
                <ul>
                    {this.state.allBooks.map(book => <li key={book}>{book}</li>)}
                </ul>

                {
                    Object.keys(this.state.outBooks).map(userId => {
                        return (
                            <div key={userId}>
                                {userId}:
                                { this.state.outBooks[userId].join("    ") }
                            </div>)})}</div>); }}export default App;
Copy the code

5. Modify data in Store

When using Redux to manage data, a common requirement is to modify data in the Store.

In Redux, we can’t modify the Store data directly, we need to go through a process:

  1. Send an Action request
  2. Reducer receives this request and modifies the data in the Store using defined functions

So, to modify Store data in a component, we first need to define an Action object, such as the one mentioned earlier:

const action_2 = {
    type: 'borrow_book'.title: 'Those things in the Ming Dynasty'.userId: '20152135'
};
Copy the code

Once the Action is defined, we need to use the store.dispatch () method in the component to trigger the Action object. Here is a very simple example:

import React from "react";
import Store from ".. /redux/Store";

class AddNewBooks extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      allBooks: Store.getState().allBooks,
      newBookName: ""
    };
  }

  setNewBooksName = (val) = > {
    this.setState({
      newBookName: val
    });
  }

  addNewBooks = () = > {
    / / define the Action
    const addBooks = {
      type: "ADD_BOOKS".newBookName: this.state.newBookName
    }
    / / triggers the Action
    Store.dispatch(addBooks);
  }

  render() {
    return (
      <>
        <div className="add-books-panel">
          <input value={this.state.newBookName} type="text" onChange={(e)= > { this.setNewBooksName(e.currentTarget.value) }} />
          <button onClick={this.addNewBooks}>Add New Boos</button>
        </div>
      </>)}}export default AddNewBooks;
Copy the code

After the Action is triggered, the Reducer function receives the request and processes the books in the Store according to the defined logic, such as the Reducer function:

import InitialState from "./InitialState";

const reducer = (state = InitialState, action) = > {
  if (action.type === "ADD_BOOKS") {
    return {
      ...state,
      allBooks: [...state.allBooks, action.newBooks]
    };
  }
  
  return state;
}

export default reducer;
Copy the code

After the Reducer function processes the books in the Store, it returns a new state, which is a snapshot of the current Store, that is, the latest data in the current Store.

By doing so, we are done updating the data in Redux.

6. Monitor Store data changes and refresh the page

When using Redux in a project, it is also common to see content in other components updated in real time as data changes in the Store. Scaling this up is easy, just use the store.subsctibe () method.

This method takes as an argument a function that Redux calls whenever state changes. If you’ve read about design patterns, until Redux uses publish-subscribe. Subscribe to Store updates through the subsctibe method, and once the Store publishes updates, Redux executes the contents of the subscription function.

Here’s an example of how to use this method:

import React from 'react'
import Store from ".. /redux/Store";

class AllBooks extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      allBooks: Store.getState().allBooks
    };
    
    // Subscribe to the data dynamics in the Redux Store. If there are changes, the contents of this function will be executed
    Store.subscribe(() = > {
      this.setState({
        allBooks: Store.getState().allBooks
      });
    });
  }

  render() {
    return (
      <div className="books-panel">
        {
          this.state.allBooks.map(_book => <p className="book-item" key={_book}>{_book}</p>)}</div>)}}export default AllBooks;
Copy the code

Write in the back

Well, that’s all about the Redux use example. I hope this simple note will help those who are new to Redux. In addition there are mistakes in the notes, but also hope that each big guy to correct.