多Slice存在同名reducer时,如何使用useDispatch?
场景说明
假设使用Redux Toolkit定义了两个Slice组件,由于数据类别不同,因此分别存储在独立的Slice组件中。现在存在一些名称相同的reducer函数,这些函数的内部代码因数据类别不同而存在差异,但reducer名称一致。
那么在此情况下,应如何使用**useDispatch**?
示例:
以下是一个使用TypeScript编写的createSlice组件:
import { createSlice } from "@reduxjs/toolkit"; type ImageStructure = { id: String; originalImage: String; croppedImage: String; zIndex: Number; posX: Number; posY: Number; }; type PayloadStructure = { payload: { id: String; originalImage: String; croppedImage: String; zIndex: Number; posX: Number; posY: Number; }; }; type RemovePayload = { payload: { id: String; }; }; export const ImgSlice = createSlice({ name: "image", initialState: Array<ImageStructure>(), reducers: { add: (state, action: PayloadStructure) => { state.push(action.payload); }, remove: (state, action: RemovePayload) => { let arr = Array<ImageStructure>(); for (let val in state) { if (state[val].id !== action.payload.id) { arr.push(state[val]); } } state = arr; }, }, }); export const { add, remove } = ImgSlice.actions; export default ImgSlice.reducer;
另一个createSlice组件如下:
import { createSlice } from "@reduxjs/toolkit"; type textStructure = { id: String; value: String; zIndex: Number; }; type PayloadStructure = { payload: { id: String; value: String; zIndex: Number; }; }; type RemovePayload = { payload: { id: String; }; }; export const textSlice = createSlice({ name: "text", initialState: Array<textStructure>(), reducers: { add: (state, action: PayloadStructure) => { state.push(action.payload); }, remove: (state, action: RemovePayload) => { let arr = Array<textStructure>(); for (let val in state) { if (state[val].id !== action.payload.id) { arr.push(state[val]); } } state = arr; }, }, }); export const { add, remove } = textSlice.actions; export default textSlice.reducer;
在上述场景中,后续可能会新增更多类型的Slice(如SVG、视频、HtmlElement等),且它们的reducer操作名称也会相同。
请问在此情况下,如何在通用React组件中使用**useDispatch**?
不可扩展的临时方案
直接修改两个Slice组件中的reducer名称,但这种方案在存在大量同名reducer的Slice组件时,扩展性很差。
推荐的可扩展解决方案
1. 导入时重命名Action
在组件中导入Action时,通过重命名区分不同Slice的同名Action,这是最直接的实现方式:
import { useDispatch } from 'react-redux'; import { add as addImage, remove as removeImage } from './imgSlice'; import { add as addText, remove as removeText } from './textSlice'; const MyComponent = () => { const dispatch = useDispatch(); const handleAddImage = (imageData) => { dispatch(addImage(imageData)); }; const handleAddText = (textData) => { dispatch(addText(textData)); }; return ( // 组件内容 ); };
2. 封装通用Dispatch工具函数
如果需要在多个通用组件中处理不同类型的Slice,可以封装一个工具函数,根据类型分发对应的Action:
// utils/dispatchUtils.ts import { Dispatch } from '@reduxjs/toolkit'; import { add as addImage, remove as removeImage } from '../slices/imgSlice'; import { add as addText, remove as removeText } from '../slices/textSlice'; type ItemType = 'image' | 'text' | 'svg'; // 后续新增类型时直接扩展 type ActionType = 'add' | 'remove'; export const dispatchItemAction = (dispatch: Dispatch, type: ItemType, action: ActionType, payload: any) => { const actionMap = { image: { add: addImage, remove: removeImage }, text: { add: addText, remove: removeText }, // 新增类型时在此处补充对应Action映射 }; const targetAction = actionMap[type][action]; if (targetAction) { dispatch(targetAction(payload)); } };
在通用组件中使用:
import { useDispatch } from 'react-redux'; import { dispatchItemAction } from './utils/dispatchUtils'; const GenericItemComponent = ({ itemType }) => { const dispatch = useDispatch(); const handleAddItem = (itemData) => { dispatchItemAction(dispatch, itemType, 'add', itemData); }; const handleRemoveItem = (itemId) => { dispatchItemAction(dispatch, itemType, 'remove', { id: itemId }); }; return ( // 通用组件内容 ); };
3. 利用Redux Toolkit自动生成的唯一Action类型
Redux Toolkit在创建Slice时,会自动将name字段与reducer名称拼接成唯一的Action类型(比如image/add、text/add),因此即使Action名称相同,它们的实际类型也不会冲突。我们只需要在导入时正确区分Action即可,无需修改reducer名称。
内容的提问来源于stack exchange,提问作者TanmayKr
相关产品推荐
相关产品推荐

