Redux-Saga在React工程架构之的应用实践详解

前言

React的作用View层次的前端框架,自然少不了很多中间件(Redux Middleware)做数据处理,而redux-saga就是其中之一,目前这个中间件在网上的资料还是比较少,估计应用的不是很广泛,但是如果使用得当,将会事半功倍的效果,下面仔细介绍一个这个中间件的具体使用流程和应用场景。

redux-saga简介

Redux-saga是Redux的一个中间件,主要集中处理react架构中的异步处理工作,被定义为generator(ES6)的形式,采用监听的形式进行工作。

redux-saga安装

使用npm进行安装:

npm install --save redux-saga

或者使用yarn:

yarn add redux-saga

redux-saga常用方法解释

redux Effects

Effect 是一个 javascript 对象,可以通过 yield 传达给 sagaMiddleware 进行执行在, 如果我们应用redux-saga,所有的 Effect 都必须被 yield 才会执行。

举个例子,我们要改写下面这行代码

yield fetch(url);

应用saga:

yield call(fetch,url)

take

等待 dispatch 匹配某个 action 。

比如下面这个例子:

.... while (true) { yield take('CLICK_Action'); yield fork(clickButtonSaga); } ....

put

触发某个action, 作用和dispatch相同:

yield put({ type: 'CLICK' });

具体的例子:

import { call,put } from 'redux-saga/effects'

export function* fetchData(action) {
   try {
      const data = yield call(Api.fetchUser,action.payload.url)
      yield put({type: "FETCH_SUCCEEDED",data})
   } catch (error) {
      yield put({type: "FETCH_Failed",error})
   }
}

select

作用和 redux thunk 中的 getState 相同。通常会与reselect库配合使用。

call

有阻塞地调用 saga 或者返回 promise 的函数,只在触发某个动作。

takeEvery

循环监听某个触发动作,我们通常会使用while循环替代。

import { takeEvery } from 'redux-saga/effects'

function* watchFetchData() {
  yield takeEvery('FETCH_REQUESTED',fetchData)
}

takeLatest

对于触发多个action的时候,只执行最后一个,其他的会自动取消。

import { takeLatest } from 'redux-saga/effects'

function* watchFetchData() {
  yield takeLatest('FETCH_REQUESTED',fetchData)
}

fork 和 cancel

通常fork 和 cancel配合使用, 实现非阻塞任务,take是阻塞状态,也就是实现执行take时候,无法向下继续执行,fork是非阻塞的,同样可以使用cancel取消一个fork 任务。

function* authorize(user,password) {
  try {
    const token = yield call(Api.authorize,user,password)
    yield put({type: 'LOGIN_SUCCESS',token})
  } catch(error) {
    yield put({type: 'LOGIN_ERROR',error})
  }
}

function* loginFlow() {
  while(true) {
    const {user,password} = yield take('LOGIN_REQUEST')
    yield fork(authorize,password)
    yield take(['logoUT','LOGIN_ERROR'])
    yield call(Api.clearItem('token'))
  }
}

上面例子中,当执行

yield fork(authorize,password)

的同时,也执行了下面代码,进行logout的监听操作。

yield take(['logoUT','LOGIN_ERROR'])

redux-saga使用案例

引入saga:

import { call,put,take,select } from 'redux-saga/effects';

创建任务:

/** * Created by Richard on 1/11/17. */
import { call,select } from 'redux-saga/effects';
import { get,getWordUrl } from '../../utils/api';
import {successFetchData } from './WordAction';

export default function* wordFlow() {
        try {
                const data = yield call(get,getWordUrl());
                yield put(successFetchData(data));
        } catch (e){

        }
}

创建saga:

import { fork } from 'redux-saga/effects';
import wordFlow from './containers/word-view/WordSaga';

export default function* rootSaga() {
  yield [
    fork(wordFlow)
  ];
}

与redux中间件进行整合:

/** * Created by Richard on 12/29/16. */
import { applyMiddleware,createStore,compose } from 'redux';

import createSagaMiddleware from 'redux-saga';

import reducers from '../reducers';

import sagas from '../sagas';

//创建saga middleware
const sagaMiddleware = createSagaMiddleware();

const middlewares = compose(applyMiddleware(sagaMiddleware)autoRehydrate());

export default function configureStore() {
        const store = createStore(reducers,undefined,middlewares);
        //运行所有已经注册的saga
        sagaMiddleware.run(sagas);
        return store;
}

下面就可以正常监听状态了。

redux-saga的优势

传统意义讲,我们很多业务逻辑要在action中处理,所以会导致action的处理比较混乱,难以维护,而且代码量比较大,如果我们应用redux-saga会很大程度上简化代码,redux-saga 本身也有良好的扩展性,非常方便的处理各种复杂的异步问题。

更多信息,请查看官方文档:

https://redux-saga.github.io/redux-saga/

相关文章

导入moment 使用方式 年月日,时分秒 星期几 相对时间 7天后 2小时后 明天 将毫秒转换成年月日
@ 一、前言 为什么介绍redux-actions呢? 第一次见到主要是接手公司原有的项目,发现有之前的大佬在处理...
十大React Hook库 原文地址:https://dev.to/bornfightcompany/top-10-react-hook-libraries-4065 原文...
React生命周期 React的生命周期从广义上分为挂载、渲染、卸载三个阶段,在React的整个生命周期中提供很...
React虚拟DOM的理解 Virtual DOM是一棵以JavaScript对象作为基础的树,每一个节点可以将其称为VNode,用...
React中JSX的理解 JSX是快速生成react元素的一种语法,实际是React.createElement(component, props, ....