react|redux-saga的使用

redux-saga 是一个用于管理应用程序副作用(例如异步获取数据,访问浏览器缓存等)的库,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。
你可能已经用了 redux-thunk 来处理数据的读取。不同于 redux thunk,你不会再遇到回调地狱了,你可以很容易地测试异步流程并保持你的 action 是干净的。
Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。现在只需要谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。
所有通常处理异步都是在组件里面写

// app.js import React, { Component } from 'react'; import { connect } from 'react-redux' import action from './store/action'class App extends Component { add = () => { // 异步的提交 setTimeout(() => { this.props.increment(this.props.number + 1) }, 1000); }render() { return ( <>
{this.props.number}
); } }const mapStateToProps = (state) => { return state }export default connect(mapStateToProps, action)(App);

// action.js import * as types from './types' export default { increment(count) { return { type: types.INCREMENT, payload: count} } }

// reducer.js import * as types from './types'let initState = { number: 0 }export default function (state = initState, action) { switch (action.type) { case types.INCREMENT: return { number: action.payload } default: return state } }

// types.js export const INCREMENT = 'INCREMENT' export const ASYNC_INCREMENT = 'ASYNC_INCREMENT'

异步都写在组件里面,代码就很难达到复用,为了解决这样的问题,redux-saga派上用场了。
redux-saga
import * as types from './types' export default { increment(count) { return { type: types.INCREMENT, payload: count } }, // 添加一个 ASYNC_INCREMENT 类型的action asyncIncrement(count) { return { type: types.ASYNC_INCREMENT, payload: count } } }

takeEvery,用于监听所有的 ASYNC_INCREMENT action,并在 action 被匹配时执行 incrementAsync 任务。incrementAsync Saga 通过 delay(1000) 延迟了 1 秒钟,然后 dispatch 一个叫 INCREMENT 的 action。
import * as types from './types' import { put, delay, takeEvery, all } from 'redux-saga/effects'export function* helloSaga() { console.log('start') } export function* incrementAsync(action) { yield delay(1000) // 使用这个函数去阻塞Generator yield put({ type: types.INCREMENT, payload: action.payload }) // 然后 dispatch 一个叫 INCREMENT 的 action }export function* watchIncrementAsync() { //用于监听所有的 ASYNC_INCREMENT action yield takeEvery(types.ASYNC_INCREMENT, incrementAsync) }export function* rootSaga() { yield all([ helloSaga(), watchIncrementAsync() ]) }

中间件需要这样配置
import { createStore, applyMiddleware } from 'redux' import reducer from './reducer' import createSagaMiddleware from 'redux-saga' import { rootSaga } from './sagas' const sagaMiddleware = createSagaMiddleware() let store = applyMiddleware(sagaMiddleware)(createStore)(reducer) sagaMiddleware.run(rootSaga) export default store

组件里面使用
import React, { Component } from 'react'; import { connect } from 'react-redux' import action from './store/action'class App extends Component { asyncAdd = () => { // dispatch 一个叫 ASYNC_INCREMENT 的 action,这个被 saga 里面的 watchIncrementAsync 函数监听了 this.props.asyncIncrement(this.props.number + 1) }render() { return ( <>
{this.props.number}
); } }const mapStateToProps = (state) => { return state }export default connect(mapStateToProps, action)(App);

【react|redux-saga的使用】现在把异步都封装到saga里面去实现异步,两者的效果一样,提高了代码的复用

    推荐阅读