react integrates native redux(3)
Preface
stay react integrates native redux(1) Based on this, redux-saga can extend reducer, which is different from redux-saga. redux-thunk saga divides redux into two parts, one is synchronous updating data, the other is asynchronous operation, the other is pure preservation, the other is logical preservation, while thunk only extends action to make action logical, both of which aim to reduce code coupling
Project creation
Reference resources react integrates native redux(1)
Increase dependency packages
yarn add redux-saga -s
src file directory
|-app.js
|-store.js
|-index.js
|-effects.js
Add effects.js file
store.js Extension Adjustment
redux-saga middleware is mainly introduced and used. The basic steps are as follows
- Saga introduces import createSaga from "redux-saga"
- Saga initializes const saga = createSaga()
- Saga uses createStore (reducer, composeWithDevTools (apply Middleware (saga)) as middleware
- Saga runs saga.run(effect)
Specific code
// store.js import { createStore, applyMiddleware } from "redux"; import createSaga from "redux-saga"; import { composeWithDevTools } from "redux-devtools-extension"; //chrome redux debugging tool import effect from "./effects"; // state Initial Value const initState = { list: ["a", "b"] }; // reducer format const reducer = (state = initState, action) => { const { type, payload } = action; // type Processing of action if (type === "SAVE") { return Object.assign({}, state, payload); } return state; }; const saga = createSaga(); /** * Instance store * Parameter 1: reducer * Parametric 2: Middleware */ export default createStore(reducer, composeWithDevTools(applyMiddleware(saga))); // Running saga, the parameter is a generator function saga.run(effect);
effects.js Additional Writing
Looking at the code, the key parts are annotated.
// actions.js import { call, put, takeEvery } from "redux-saga/effects"; const fetchListEffect = function*(action) { const { payload } = action; // Asynchronous operations can directly call functions that return promise s, such as fetch.axios, etc. Officially recommended encapsulation with call, see updateListApi specifically. const { data } = yield new Promise(resolve => { setTimeout(() => { const data = { code: 0, msg: "ok", data: { list: ["hello", "saga"], payload } }; resolve(data); }, 2000); }); yield put({ type: "SAVE", payload: data }); // Here put is the encapsulation of store.dispatch }; /** * This function can be split into service files to further reduce coupling * @param {Parameter} payload */ const updateListApi = payload => { return new Promise(resolve => { setTimeout(() => { const data = { code: 0, msg: "ok", data: { list: ["hello", "saga", "update"], payload } }; resolve(data); }, 1000); }); }; const updateListEffect = function*(action) { const { payload } = action; const { data } = yield call(updateListApi, payload); // The official recommendation for asynchronous data operations is to call parameter 1 as a function returning promise and parameter 2 as a transfer parameter. yield put({ type: "SAVE", payload: data }); }; // saga calls generator functions export default function*() { // takeEvery parameter 1 is an action type name parameter 2 is a generator function yield takeEvery("fetch/list", fetchListEffect); yield takeEvery("update/list", updateListEffect); }
Use, app.js rewrite
Main operation
useEffect(() => { store.dispatch({ type: "fetch/list", payload: { id: 1 } }); }, []);
onClick={() => store.dispatch({ type: "update/list" })}
Complete code
// app.js import React, { useState, useEffect } from "react"; import store from "./store"; export default () => { // Get the state in the store and put it in the hook function, similar to this.setState(store.getState()) const [state, setState] = useState(store.getState()); useEffect(() => { // Store subscription function, which is automatically executed when the state changes through store.dispatch distribution action store.subscribe(() => { setState(store.getState()); //Reset the value of component state to update the view }); }, []); // [] Represents only one execution const { list } = state; const addList = () => { list.push(Date.now()); store.dispatch({ type: "SAVE", payload: { list } }); //Distributing an action object }; // Initialization request data saga mode useEffect(() => { store.dispatch({ type: "fetch/list", payload: { id: 1 } }); }, []); return ( <div> <button onClick={addList}>add</button> {/* Click Event Definition, saga Mode */} <button onClick={() => store.dispatch({ type: "update/list" })}> update </button> <ul> {list.map(v => { return <li key={v}>{v}</li>; })} </ul> </div> ); };
Above is the complete construction and use of redux+redux-saga. Complete code
If you find it too cumbersome, there is a good framework for integrating saga, such as dva.js,umi.js It's ready to use.