如何在redux-offline的effect中按名称/类型调用redux toolkit的async thunk
解决方案
方案1:Thunk名称映射(完全匹配你的预期实现思路)
你设想的通过字符串名称调用AsyncThunk的方案完全可行,只需要提前将所有需要在离线场景调用的AsyncThunk注册到可序列化的映射表中即可:
- 单独创建Thunk注册文件
thunkRegistry.js,统一管理所有需要离线调用的Thunk:
// 引入你所有slice中导出的asyncThunk import { fetchUser, updateUser } from './userSlice' import { createOrder, cancelOrder } from './orderSlice' // key为创建asyncThunk时传入的第一个参数(即Thunk的type前缀) export const thunkRegistry = { 'user/fetchUser': fetchUser, 'user/updateUser': updateUser, 'order/createOrder': createOrder, 'order/cancelOrder': cancelOrder }
- 配置redux-offline的自定义effect:
import { thunkRegistry } from './thunkRegistry' const customOfflineConfig = { // 其余原有配置保持不变 effect: (effectParams) => { const { thunkType, payload } = effectParams const targetThunk = thunkRegistry[thunkType] if (!targetThunk) throw new Error(`未注册的Thunk类型:${thunkType}`) // 直接dispatch对应Thunk,返回的Promise会被redux-offline自动处理 return store.dispatch(targetThunk(payload)) } }
- 触发离线Action的写法和你预期的完全一致:
dispatch({ type: 'someOfflineAction', meta: { offline: { effect: { thunkType: 'user/updateUser', payload: { id: 1, name: '新用户名' } } } } })
该方案完全规避了函数无法序列化的问题,存储到本地的只有可序列化的字符串和普通数据,和你使用createSlice的场景完全兼容。如果项目Thunk数量较多,也可以写自动化脚本遍历所有slice文件自动生成映射表,不需要手动维护。
方案2:逻辑抽离复用(无需维护Thunk映射表)
如果你不想额外维护映射表,可以把AsyncThunk中的请求逻辑抽成公共函数,在effect中直接调用公共函数后手动触发对应状态Action:
- 抽离公共请求逻辑:
// userApi.js export const updateUserApi = (payload) => { return fetch(`/api/users/${payload.id}`, { method: 'PUT', body: JSON.stringify(payload) }).then(res => res.json()) }
- 创建AsyncThunk时复用公共逻辑:
import { createAsyncThunk } from '@reduxjs/toolkit' import { updateUserApi } from './userApi' export const updateUser = createAsyncThunk('user/updateUser', updateUserApi)
- 在effect中直接调用公共请求函数:
const customOfflineConfig = { effect: (effectParams) => { const { apiName, payload, successAction, failAction } = effectParams const apiFunc = apiRegistry[apiName] // 仅需要注册请求函数映射,比Thunk映射更轻量 return apiFunc(payload) .then(res => { store.dispatch({ type: successAction, payload: res }) return res }) .catch(err => { store.dispatch({ type: failAction, payload: err, error: true }) throw err }) } }
内容的提问来源于stack exchange,提问作者holyris
相关产品推荐
相关产品推荐

