优雅的redux异步中间件 redux-effect
不吹不黑,redux蠻好用。只是有時(shí)略顯繁瑣,叫我定義每一個(gè)action、action type、使用時(shí)還要在組件上綁定一遍,臣妾做不到呀!下面分享一種個(gè)人比較傾向的極簡(jiǎn)寫法,仍有待完善,望討論。
github: github.com/liumin1128/…
基于redux、async/await、無侵入、兼容性良好的異步狀態(tài)管理器。
install
npm i -S redux-effect// or yarn add redux-effect 復(fù)制代碼use
import { createStore, applyMiddleware, combineReducers } from 'redux'; import { reduxReduers, reduxEffects } from 'redux-effect';const models = [ test1, test2, ...];const reducers = combineReducers(reduxReduers(models)); const middlewares = [ reduxEffects(models) ];const store = createStore(reducers,initialState,middlewares); 復(fù)制代碼從代碼可以看出,從reduxReduers, reduxEffects中得到的就是標(biāo)準(zhǔn)的reducer和middleware,完美兼容其他redux插件,也可以輕松整合進(jìn)老項(xiàng)目中。
完整例子:example
model
在redux-effect中,沒有action的概念,也不需要定義action type。
所有關(guān)于某個(gè)state的一切聲明在一個(gè)model中,本質(zhì)就是一個(gè)對(duì)象。
export default {namespace: 'test',state: { text: 'hi!' },reducers: {save: (state, { payload }) => ({ ...state, ...payload }),clear: () => ({})},effects: {fetch: async ({ getState,dispatch }, { payload }) => {await sleep(3000);await dispatch({ type: 'test/clear' });await sleep(3000);await dispatch({ type: 'test/save', payload: { text: 'hello world' } });}} };復(fù)制代碼namespace:
model的命名空間,對(duì)應(yīng)state的名字,必填,只接受一個(gè)字符串。
state:
state的初始值,非必填,默認(rèn)為空對(duì)象
reducers:
必填,相當(dāng)于同步執(zhí)行的action方法,接受兩個(gè)參數(shù)state和action,合并后返回新的state狀態(tài)值。
effects:
非必填,相當(dāng)于異步執(zhí)行的action方法,接受兩個(gè)參數(shù)store和action,store里包括redux自帶的getState和dispatch方法,action為用戶dispatch時(shí)帶的參數(shù)。
dispatch
這里的dispatch就是redux中的dispatch,但有幾個(gè)約定。
定義每一個(gè)action,并將其綁定到視圖層過于繁瑣,去action化則讓事件的觸發(fā)變的靈活。
普通事件
發(fā)送事件時(shí),不區(qū)分同步還是異步,只管dispatch,一切都已在model中定義好。
// 同步 dispatch({ type: 'test/save', payload: { text: "hello world" } }) // 異步 dispatch({ type: 'test/fetch' }) 復(fù)制代碼等待
等待一個(gè)事件完成再執(zhí)行邏輯,dispatch方法是可以被await的,十分輕松。
async function test() {await dispatch({ type: 'test/fetch' })await console.log('hello world') } 復(fù)制代碼回調(diào)
等待某個(gè)事件,再執(zhí)行外部定義的某個(gè)回調(diào)函數(shù),只需要在action字段里加上callback方法,在effect中調(diào)用即可。
相比較await,回調(diào)可以拿到某些返回值,也可以在effect流程的中間部分執(zhí)行。
dispatch({ type: 'test/fetch', callback1, callback2 }){effects: {fetch: async ({ getState,dispatch }, { payload, callback, callback2 }) => {const state = await getState()await sleep(3000);await callback1(state)await sleep(3000);await callback2(state)}} } 復(fù)制代碼自定義reducer
reducer其實(shí)就是redux中的reducer,用法完全一樣。比如定義一個(gè)push方法,將后續(xù)數(shù)據(jù),壓入到原有數(shù)據(jù)后面,可以這樣寫。
export default {namespace: 'test',state: { data: [] },reducers: {save: (state, { payload }) => ({ ...state, ...payload }),clear: () => ({}),push: (state, { payload = {} }) => {const { key = 'data', data } = payload;return { ...state, [key]: state[key].concat(data) };}}, }; 復(fù)制代碼自定義effect
effect其實(shí)就是一個(gè)普通async函數(shù),接受store和action兩個(gè)參數(shù),可以使用async/await,可以執(zhí)行任意異步方法,可以隨時(shí)拿到state的值,可以dispatch觸發(fā)另一個(gè)effect或者reducer。
loading
也許你會(huì)想監(jiān)聽某個(gè)effect,拿到loading狀態(tài),以便在ui給用戶一個(gè)反饋。一般情況下監(jiān)聽一個(gè)異步方法,只需要在effect的開頭和結(jié)束,各自設(shè)定狀態(tài)即可,與常規(guī)寫法無異。
但這里也提供一種model級(jí)別的loading狀態(tài),新增一個(gè)名為loading的model,再使用reduxEffectsWithLoading包裹需要監(jiān)聽的model即可。
關(guān)于model-creator
以上所做的事情,是將redux核心規(guī)范為model,得到了統(tǒng)一且可以復(fù)用的數(shù)據(jù)模型,這為自動(dòng)生成model創(chuàng)造了可能性,如果能通過工廠模式,自動(dòng)化創(chuàng)建具有類似功能,且可以隨意裝配的model,一切將變得更加美好。
Coming Soon
總結(jié)
以上是生活随笔為你收集整理的优雅的redux异步中间件 redux-effect的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring cloud eureka服
- 下一篇: Chrome运行时性能瓶颈分析