review

  • React (1) Uncover the JSX syntax and virtual DOM
  • React (2) Implement a simple version of HTML +redux.js demo
  • React uses redux to implement a simplified counter in React
  • React redux-Saga (redux-Saga
  • React (5) DVA (Zero Configuration)

Today’s demo is to implement an asynchronous calculator that explores the Redux-Saga workflow

Introduction to the

  • Redux-saga is a middleware for Redux, and the purpose of middleware is to provide additional functionality for Redux.
  • Because all operations in reducers are synchronous and pure, that is, reducer are pure functions. Pure functions mean that the return result of a function only depends on its parameters and will not have external side effects in the execution process, that is, spit out whatever is sent to it.
  • But in real application development, we want to do asynchronous (such as Ajax requests) and non-pure operations (such as changing external state), which are called “side effects” in the functional programming paradigm.

Redux-saga is one of the middleware designed to handle these side effects (asynchronous tasks). It is a process manager who receives events and may trigger new events, managing complex processes for your application.

How redux-Saga works

  • For those who are not familiar with generator, see Ruan Yifeng generator
  • Sages use a Generator function to yield Effects (text objects containing instructions).
  • The purpose of the Generator function is to pause execution and resume execution where it was paused
  • An Effect is a simple object that contains some information for middleware to explain execution.
  • You can create effects by using the Effects API such as fork, Call, take, Put, cancel, etc.

Redux of saga

  • Worker saga does the left and right work, such as calling apis, making asynchronous requests, and getting the results of asynchronous encapsulation
  • Watcher Saga listens to the actions dispatched and calls the worker to execute the task when it receives the action or knows that it is triggered
  • Root Saga immediately launches the only entry to Saga

The basic introduction has been covered. After a demo, go back to the redux-Saga website or the explanation above to get a better understanding

Implement an asynchronous counter using Redux-Saga

As the structure of the table of contents is the same as in the previous article, only the parts of the changes are isolated and explained here

  • React uses redux to implement a simplified counter in React

1, modify actions/counter.js

  • Added an action type for asynchronous counting.
import * as Types from ".. /action-types";
let actions ={
    add(num){
        return{type:Types.INCREMENT,count:num}
    },
    minus(num){
        return{type: Types. The DECREMENT, count: num}}, / / adds an asynchronous notation, Types, is used to counter. Distributed in js action async (num) {return {type:Types.ADD_ASYNC}
    }
};
export default actions;

Copy the code

Add saga.js file to SRC directory

//takeEvery=> responsible for listening put=> send action call=> tell saga, execute delay, and pass 1000 as parameter import {takeEvery,put,call} from"redux-saga/effects";
import * as Types from "./store/action-types";
const delay = ms=>new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve()},ms)}) // Saga is divided into three types: 1. Rootsaga 2function* add() { yield call(delay,1000); // If the saga middleware sends an action to the repository, yield put({type:Types.INCREMENT,count:10});
}
function* watchAdd() {yield takeEvery(types.add_async,add)}export default function* rootSaga() {
    yield watchAdd()

}
Copy the code

Rudux-saga: Root Saga -> Watcher Saga -> Worker Saga And as we’ll see in this code, we look at the code from the top down.

2.1 Saga Workflow (Code from bottom up)
  • RootSaga, the saga entry file, is exported by default
  • Watcher saga ->wactchAdd is responsible for listening to the action that is sent out. If the action type matches, the corresponding worker saga will be executed
  • The worker Saga above refers to the Add function
2.2 Redux-saga/Effects

In real application development, we want to do asynchronous (such as Ajax requests) but non-pure operations (such as changing external state), which are called “side effects” in the functional programming paradigm.

  • TakeEvery => is responsible for listening, listening to the action sent to the warehouse, if the action type matches, will execute the corresponding listener generator ->add
  • Put => Dispatch an action
  • Call => tell Saga to execute the delay function and pass the parameters. Note that the delay function must return promise

With that said, the process is done and rootSaga is executed in the store

3. Introduce rootSaga in store/ Index

    import {createStore,applyMiddleware} from 'redux';
    import createSagaMiddleware from "redux-saga"; // redux-saga import rootSaga from".. /saga"RootSaga import reducer from"./reducers"
    letsagaMiddleware =createSagaMiddleware(); // Execute to get saga middlewareletstore = createStore(reducer,applyMiddleware(sagaMiddleware)); // Use middleware sagamiddleware. run(rootSaga); // Start executing rootSagaexport  default  store;
Copy the code

Redux middleware is not explained. This part involves a lot of things and is not easy to understand. The purpose of writing this react series is to make it as simple as possible for everyone to understand.

4. Dispatch the asynchronous action in the counter. Js component

  • The code is exactly the same as in the previous article, except for the addition of buttons for asynchronous operations
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {connect} from "react-redux";
import actions from ".. /store/actions/counter"
class Counter extends Component {
    render() {
        console.log(this.props);
        return( <div> <h1>{this.props.number}</h1> <button onClick={()=>{this.props.add(5)}}>+</button> <button OnClick = {() = > {this. Props. Minus (1)}} > - < / button > / / increase asynchronous operations < button onClick = {() = > {this. Props. Async ()}} > asynchronous plus 10 < / button > < / div > )}}exportdefault connect(state=>({ ... state }),actions)(Counter)Copy the code

Final. look at that. As you can see, click and wait 1 second before adding 10. Call () can then be passed in asynchronous functions (such as Ajax) that are executed to retrieve data. The delay function corresponding to our example

Finally, comb the whole process

  • The action object =>{type: types.add_async} that is returned after this.props. Async () is called in the connect method

  • 2. TakeEvery (types.add_async,add) in saga, and trigger worker saga after monitoring the type of action =>add

  • In worker saga, first yield call(delay,1000); Run the delay method for 1s

  • 4, yield the put ({10} type: Types. The INCREMENT, the count:); The last one is still the INCREMENT type

  • 5. The reducer was then processed and state was updated

  • 6. Page refresh

  • More quality articles for reference

  • Redux all source code parsing stamp here