1 分钟带你入门 Redux 中间件

用户头像
Leo
关注
发布于: 2020 年 10 月 21 日
1分钟带你入门 Redux 中间件

前言:欢迎再次光临我的1分钟系列,看到这里的小伙伴应该对Redux有了一个基本了解了,如果不是最好通过官网了解一下,或者看看这个1 分钟带你入门 Redux、React-Redux



基本原理

我们首先来想个问题,假如你是Redux的设计者,你会把这个中间件安排的哪个环节呢?

button这个按钮是交给用户操作的,reducer是个纯函数用来处理state,而state又和view相互对应,所以dispatch这个阶段是个最佳选择



import {createStore, combineReducers, compose, applyMiddleware} from 'redux'
// 合并reducer
const rootReducer = combineReducers({
counter,
lister
})
// compose 合并function
const enhancerCompose = (...arg) => {
if (window.__REDUX_DEVTOOLS_EXTENSION__) {
arg.unshift(window.__REDUX_DEVTOOLS_EXTENSION__()) // redux-devtools工具
}
return compose(...arg)
}
// applyMiddleware 中间件合并工具
const store = createStore(rootReducer, initalState, enhancerCompose(applyMiddleware()))



... 接上文
// middleWare one by one
function sleep(){...}
// 中间件a
const a = store => next => async action => {
console.log('a start')
await sleep(1000)
console.log('a end')
return next(action)
}
// 中间b
const b = store => next => action => {
console.log('b')
return next(action)
}
const store = createStore(rootReducer, initalState, enhancerCompose(applyMiddleware(a,b)))
// 触发dispatch时
store.dispatch(...)
// 控制台输出:
// console.log ==> a start
// 1000ms later
// console.log ==> a end
// console.log ==> b
...



不难发现,中间件是在store创建时注入的,然后运行的时候是按照中间排列的顺序一个接着一个执行

再来看看下面这张图,让你对他的数据流转会更加的清晰

数据流转

  • View视图(页面)上触发了一个事件或者啥东西,需要修改某个状态

  • 然后创建一个Action到Dispatch里面

  • Dispatch里面的中间件完成一些操作后(Side Effect),又重新创建一个新的Action

  • 直到中间件MiddleWare里所有的函数全部执行完成,才触发Reducer

  • Reducer更新完State后就是通知View渲染新的数据



相信你头脑中刻上这两个模型后,Redux算是彻底被你攻克了,剩下的就是工程上的实践,你还可先看看文档,如:

此外,我再给你简述一下redux-saga吧

中间件 Redux-Saga 简介

redux-saga也是redux的一种中间件,它的创建过程是这样子的:

...
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import rootSaga from './sagas'
...
const reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
const sagaMiddleware = createSagaMiddleware() // 创建sagaMiddleware
const store = createStore(reducer, applyMiddleware(sagaMiddleware)) // 注入store
sagaMiddleware.run(rootSaga) // 让saga跑起来
...

再来看看saga.js这个文件干了些啥

import { put, takeEvery, all, takeLatest, takeLeading, takeMaybe } from 'redux-saga/effects'
const delay = (ms) => new Promise(res => setTimeout(res, ms))
function* helloSaga() {
console.log('Hello Sagas!')
}
function* incrementAsync() {
yield delay(1000)
yield put({ type: 'INCREMENT' }) // 调用Reducer函数里面定义的INCREMENT
}
// 可以理解为声明了一个叫做INCREMENT_ASYNC的Action
function* watchIncrementAsync() {
yield takeLeading('INCREMENT_ASYNC', incrementAsync)
}
// 合并 saga
export default function* rootSaga() {
yield all([
helloSaga(),
watchIncrementAsync()
])
}

然后组件上调用可以是这样子的:

...
// 组件
function CounterCom() { ... }
// 将dispatch挂载至props
const mapDispatchToProps = dispatch => {
const action = type => dispatch({type})
return {
onIncrement: () => action('INCREMENT'),
onDecrement: () => action('DECREMENT'),
onIncrementAsync: () => action('INCREMENT_ASYNC')
}
}
// connect
const Counter = connect(mapStateToProps, mapDispatchToProps)(CounterCom)

不难发现saga基本上可以做到代码无侵入性,并优雅的实现dispatch的异步功能;也就是说原来的代码可以不用修改,仅仅是在全局创建声明时注入saga中间件,然后在需要的地方编写saga.js异步action



当然saga的功能还不仅仅如此,你还可以观摩官方文档,从而发现更多强大的地方!



参考:

发布于: 2020 年 10 月 21 日阅读数: 59
用户头像

Leo

关注

读书点亮生活, 2019.01.16 加入

Polo MI

评论

发布
暂无评论
1分钟带你入门 Redux 中间件