什么是 Redux 中间件
中间件允许我们扩展 redux 应用程序
中间件本质就是一个函数
增强和扩展体现在什么地方呢?体现在对 action 的处理能力上,之前 action 是直接被 reducer 处理的,但是加入中间件以后,当组件触发 action 后,action 会优先被中间件处理,当中间件处理完后再把该 action 传递给reducer,让 reducer 继续处理 action。
加入了中间件后 Redux 的工作流程
开发 Redux 中间件
开发中间件的模板代码
export default store => next => action => { }
中间件在开发完成以后只有被注册才能在 Redux 的工作流程中生效
import { createStore, applyMiddleware } from 'redux';
import logger from './middleware/logger';
createStore(reducer, applyMiddleaware(logger));
打印 action 操作日志示例:
const logger = store => next => action => {
console.log(action);
next(action);
}
export default logger;
中间的执行顺序取决于注册顺序,如下 先执行 logger 后执行 test最后传递给 reducer 执行。
createStore(reducer, applyMiddleaware(logger, test));
中间件开发实例
thunk 中间件可以让我们在 Redux 的工作流中加入异步代码
export default store => next => action => {
if (typeof action === 'function') {
action(store.dispatch);
return;
}
next(action);
}
此时异步 action creator返回是函数,函数里包含异步操作,异步操作完毕后调用 dispatch 触发 action 传递给 reducer
export const increment_async = payload => dispatch => {
setTimeout(() => {
dispatch(increment(payload))
}, 2000)
}
Redux 常用中间件
redux-thunk
允许在 redux 工作流当中加入异步操作,与上面自己实现的 thunk 类似
- 下载
npm install redux-thunk
- 引入 redux-thunk
import thunk from 'redux-thunk';
- 注册 redux-thunk
import { applyMiddleware } from 'redux';
createStore(rootReduer, applyMiddleware(thubk));
- 使用 redux-thunk 中间件
const fetchPosts = () => async dispatch => {
const posts = await axios.get('api/posts').then(res => res.data);
dispatch({ type: 'FETACHPOSTS', payload: posts });
}
redux-saga
redux-saga 与 redux-thunk 作用是一样的都是允许在 redux 工作流当中加入异步操作。redux-saga 与 redux-thunk 相比它的功能更加强大。
redux-saga 解决的问题
redux-saga 可以将异步操作从 Action Creator 文件中抽离出来,放在一个单独的文件中。
redux-saga 使用
- 下载
npm install redux-saga
- 创建 redux-saga 中间件
import createSagaMiddleware from 'redux-saga';
const sagaMiddleware = createSagaMiddleware();
- 注册 sagaMiddleware
createStore(reducer, applyMiddleware(sagaMiddleware));
- 使用 saga 接收 action 执行异步操作
import { takeEvery, put, delay } from 'redux-saga/effects;'
function* increment_async_fn () {
yield delay(2000);
yield put(increment(10))
}
export default function* counterSaga () {
yield takeEvery(INCREMENT_ASYNC, increment_async_fn);
}
takeEvery
用于接收 action, put
用于触发另一个 action,当异步操作返回结果后,需要通过 put
触发 action 将该异步操作的结果传递给 reducer,让 reducer 将该数据保存在 store 当中。
INCREMENT_ASYNC
是组件中dispatch触发的 action.type,increment 是传递给reducer的 action creator 。
- 启动 saga
import postSaga form './store/sagas/post/post.saga';
sagaMiddleware.run(postSaga);
- action 传参 组件触发 action 的时候如何传参?
<button onClick={() => props.increment_async(20)}>
+
</button>
function* increment_async_fn (action) {
yield delay(2000);
yield put(increment(action.payload));
}
- saga 文件的拆分与合并
import { all } from 'redux-saga/effects';
import counterSaga from './counter.saga';
import modalSaga from './modal.saga';
export default function* rootSaga () {
yield all([
counterSaga(),
modalSaga()
])
}
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas/root.saga';
const sagaMiddleware = createSagaMiddleware();
sagaMiddleware.run(rootSaga);
redux-actions
redux-actions 解决的问题
redux 流程中大量的样板代码读写很痛苦,使用 redux-actions 可以简化 Action 和 Reducer 的处理。
redux-actions 使用
- 下载
npm install redux-actions
- 创建 Action
import { createAction } from 'redux-actions';
const increment_action = createAction('increment');
const decrement_action = createAction('decrement');
createAction 帮助我们生成 action creator 函数
- 创建 Reducer
import { handleAction as createReducer } from 'redux-actions';
import { increment_action, decrement_action } from '../actions/counter.actions';
const initialState = { count: 0 };
const counterReducer = createReducer({
[increment_action]: (state, action) => ({ count: state.count + 1 }),
[decrement_action]: (state, action) => ({ count: state.count - 1 }),
}, initialState);
export default counterReducer;