能否不导入action即可dispatch redux-thunk动作?参考redux-saga调用方式
redux-thunk实现同saga无导入直接dispatch的方案
结论
可以实现,核心思路是在redux-thunk之上封装一层自定义中间件做type映射,不需要修改redux-thunk本身的逻辑,最终使用体验和saga完全一致。
实现原理
redux-thunk默认只会处理函数类型的action,遇到普通对象类型的action会直接透传给下一个中间件/reducer。我们只要在thunk中间件之前加一层自定义拦截逻辑,匹配到指定type的普通对象action时,自动映射到对应的thunk函数执行即可。
具体实现步骤
- 统一维护thunk逻辑,单独创建模块文件比如
posts.thunks.js,建立type到thunk函数的映射:
// posts.thunks.js export const postThunksMap = { // key为你要dispatch的action type,value为对应thunk函数 THUNK_GET_POSTS: (payload) => async (dispatch, getState) => { // 原有业务逻辑 const res = await fetch(`/api/posts?filter=${payload}`) const posts = await res.json() dispatch({ type: 'SET_POSTS', payload: posts }) } // 所有帖子相关thunk都可以统一放在这个文件里维护 }
- 编写自定义中间件,完成action到thunk的自动映射:
// thunkAutoLoader.middleware.js import { postThunksMap } from './posts.thunks.js' const thunkAutoLoader = store => next => action => { // 匹配到映射表中存在的type,就生成对应thunk函数交给thunk中间件执行 if (postThunksMap[action.type]) { const thunkFunc = postThunksMap[action.type](action.payload) return store.dispatch(thunkFunc) } // 未匹配到的action正常走后续流程 return next(action) } export default thunkAutoLoader
- 注册中间件时注意顺序,自定义中间件要放在redux-thunk之前:
import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' import thunkAutoLoader from './thunkAutoLoader.middleware.js' import rootReducer from './reducers' const store = createStore( rootReducer, applyMiddleware(thunkAutoLoader, thunk) )
使用效果
配置完成后,你可以在任意组件内直接调用普通对象格式的dispatch,不需要提前导入任何thunk相关的action:
// 组件内无需导入任何post相关的action dispatch({type: 'THUNK_GET_POSTS', payload: 'all'})
所有thunk逻辑可以按业务模块统一拆分维护,和saga的使用体验完全一致。
内容的提问来源于stack exchange,提问作者rendom
相关产品推荐
相关产品推荐

