redux-saga

542 阅读2分钟

参考文档1

参考文档2

博客文档参考1

遇到saga监听函数反复执行问题解决参考

  • redux-saga是通过ES6中Generator实现的,本质是一个可以自执行的generator

  • 通过dispatch(action)进行触发,然后通过监听action.type,其中值得注意的是takeEvery监听的action.type不要和put触发action.type一样,不然会反复执行

  • put相当于dispatch一样的效果

  • redux-saga 跟 redux-thunk 区别就在于 redux-saga 独立出一个单独的文件,通过自身的API来监听dispatch的action.type,来进行一些其他的操作,然后再通过自身的API(put方法)其他重新dispatch给reducer进行操作。

  • redux-thunk的效果就是让dispatch(action)变为也可以dispatch(function),当dispatch函数的时候,会自动执行该函数,然后在函数里做一些其他操作,最后在函数里重新dispatch(action)

16d1f0ebf3a5f6f0.jpg

基本用法介绍

  • 其他不用细看主要看saga文件,我此处的action以及action.type都不是通过变量返回,actionTypes.js和actionCreators.js虽然定义了,但为了方便和直观不使用变量。

  • 至于reducer也是定义好的,主要就是判断action.type然后操作state数据,跟redux-saga和redux-thunk的应该并不影响。

image.png

// store/index.js
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducer'
import createSagaMiddleware from 'redux-saga'
import rootSaga from './saga'

// 创建saga中间件
const sagaMiddleware = createSagaMiddleware()

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// 创建store
const store = createStore(reducer, composeEnhancers(applyMiddleware(sagaMiddleware)))

// 使用saga,好像得放到createStore后面
sagaMiddleware.run(rootSaga)
export default store
// store/reducer.js
// 返回一个reducer函数,让createStore用来创建store
// 导入actionTypes.js中的type类型,方便我们进行识别操作
import {
  A,
  B
} from './actionTypes.js'

// formJS将JS对象转化为immutable对象
import { fromJS } from 'immutable'
const defaultState = fromJS({
  valueA: '',
  valueB: ''
})

// 只能间接修改state
const reducer = (state = defaultState, action) => {
  if (action.type === A) {
    return state.set('valueA', action.value)
  } else if (action.type === B) {
    return state.set('valueB', action.value)
  }
  return state
}

export default reducer

image.png

image.png

  • saga.js

image.png

// import { A } from './actionTypes';
import { takeEvery, put } from 'redux-saga/effects';

function* getInitList() {
  console.log(1)
  try {
    yield put({
      type: 'A',
      value: 'milo'
    });
  } catch (e) {
    console.log(e);
  }
}

export default function* rootSaga() {
  yield takeEvery('CHANGE', getInitList);
}
  • 组件直接dispatch(action),saga就可以监听到了

image.png

image.png

多个saga合并成一个根saga,跟多个reducer一样

image.png

  • 根store,项目文件/src/store/index.js
import { createStore, compose, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducer';
import rootSaga from './saga'

const sagaMiddleware = createSagaMiddleware()

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(sagaMiddleware)));
sagaMiddleware.run(rootSaga)
export default store;
  • src/store/reducer.js

image.png

  • src/store/saga.js

image.png

import { fork, all } from 'redux-saga/effects'

// 异步逻辑
import { homeSaga } from './../pages/home/store'
import { loginSaga } from './../pages/login/store'

// 单一进入点,一次启动所有Saga
export default function* rootSaga() {
  yield all([fork(homeSaga), fork(loginSaga)])
}
  • home组件的store/index.js

image.png

  • home组件的store/reducer.js

image.png

  • home组件的store/saga.js

image.png

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

function* getInitList() {
  console.log(1)
  try {
    yield put({
      type: 'HOME_TYPE',
      value: '你好,milo'
    });
  } catch (e) {
    console.log(e);
  }
}

export function* homeSaga() {
  yield takeEvery('CHANGE_HOME', getInitList);
  yield takeEvery('CHANGE_A', getInitList);
}

  • home组件进行dispatch

image.png

image.png

  • login组件跟home组件一样

redux-saga 中的 API