在上一篇 已成功把redux
添加到项目, 现在再把redux-saga
添加进来.
这篇 是使用redux-thunk
, 可以跟这篇做个对比看下redux-thunk
和redux-saga
使用上的区别.
这一次做个跑秒器. 点击开始
按钮就开始跑秒,点击停止
按钮停止跑秒, 点击重置
按钮时间就清零. 跑秒状态下数字为蓝色,停止状态下为黑色.
先在package.json
里添加redux-saga
库, 并在目录下npm install
:
"dependencies": { ... "redux-saga": "^0.11.0"},
把action
名字改得更有意义点, actionsTypes.js
:
export const START = 'START';export const STOP = 'STOP';export const RESET = 'RESET';export const RUN_TIMER = 'RUN_TIMER';
actions.js
跟着改:
import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';const start = () => ({ type: START });const stop = () => ({ type: STOP });const reset = () => ({ type: RESET });const runTime = () => ({ type: RUN_TIMER });export { start, stop, reset, runTime}
reducers.js
在action
改变后也需要调整:
import { combineReducers } from 'redux';import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';// 原始默认stateconst defaultState = { seconds: 0, runStatus: false}function timer(state = defaultState, action) { switch (action.type) { case START: return { ...state, runStatus: true }; case STOP: return { ...state, runStatus: false }; case RESET: return { ...state, seconds: 0 }; case RUN_TIMER: return { ...state, seconds: state.seconds + 1 }; default: return state; }}export default combineReducers({ timer});
添加一个sagas.js
文件, 处理项目的业务逻辑:
import { takeEvery, delay, END } from 'redux-saga';import { put, call, take, fork, cancel, cancelled } from 'redux-saga/effects';import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';import { stop, runTime } from './actions';function* watchStart() { // 一般用while循环替代 takeEvery while (true) { // take: 等待 dispatch 匹配某个 action yield take(START); // 通常fork 和 cancel配合使用,实现非阻塞任务,take是阻塞状态,也就是实现执行take时候,无法向下继续执行,fork是非阻塞的,同样可以使用cancel取消一个fork 任务 var runTimeTask = yield fork(timer); yield take(STOP); // cancel: 取消一个fork任务 yield cancel(runTimeTask); }}function* watchReset() { while (true) { yield take(RESET) yield put(stop()); }}function* timer() { try { while(true) { // call: 有阻塞地调用 saga 或者返回 promise 的函数,只在触发某个动作 yield call(delay, 1000); // put: 触发某个action, 作用和dispatch相同 yield put(runTime()); } } finally { if (yield cancelled()) { console.log('取消了runTimeTask任务'); } }}export default function* rootSaga() { yield fork(watchStart); yield fork(watchReset)}
把saga
作为中间件添加进store
, store.js
如下:
import { createStore, applyMiddleware, compose } from 'redux';import createSagaMiddleware, { END } from 'redux-saga';import createLogger from 'redux-logger';import rootReducer from './reducers';import sagas from './sagas';const configureStore = preloadedState => { const sagaMiddleware = createSagaMiddleware(); const store = createStore( rootReducer, preloadedState, compose ( applyMiddleware(sagaMiddleware, createLogger()) ) ) sagaMiddleware.run(sagas); store.close = () => store.dispatch(END); return store;}const store = configureStore();export default store;
OK, 大功告成, commond+R
运行.