Redux Slice全局函数控制指定菜单失效问题求助
Redux Slice控制指定菜单显示问题修复
问题概述
我创建了一个Redux Slice存储open(布尔值)和name(字符串)状态,用来控制仅打开目标菜单。将该Slice用于包含两个菜单的组件后,点击任意菜单的IconButton,菜单都无法打开。希望通过name参数指定打开对应菜单,不想在组件中使用本地状态,仅用单个Redux Slice实现。
错误分析
原代码存在以下几个关键问题:
- 错误导出action:最后一行导出的是
dialogSlice.actions的setOpenDialog,而非当前testSlice的action,导致dispatch的action无法正确更新testDialog的状态。 - 不必要的createAsyncThunk:这里没有异步操作,完全不需要用
createAsyncThunk,直接调用reducer对应的action即可,冗余的异步逻辑反而可能引发问题。 - Reducer参数处理错误:
setOpenDialogreducer中,action.payload是包含open和name的对象,但代码直接把整个payload赋值给state.name,导致state.name变成了对象而非字符串,组件中name === 'menuA'的判断永远不成立。
修正后的代码
1. 修正Redux Slice代码
import { createSlice } from "@reduxjs/toolkit"; export interface TestState { open: boolean; name: string; } const initialState: TestState = { open: false, name: '' } export const testSlice = createSlice({ name: 'testDialog', initialState, reducers: { // 打开指定菜单 setOpenDialog: (state, action) => { state.open = true; state.name = action.payload; // payload直接传入菜单名称字符串 }, // 新增关闭菜单的action closeDialog: (state) => { state.open = false; state.name = ''; } } }); // 导出当前testSlice的action,而非dialogSlice的 export const { setOpenDialog, closeDialog } = testSlice.actions;
2. 修正组件代码
import { useDispatch, useSelector } from "../../Redux/reduxStore"; import { setOpenDialog, closeDialog } from "./path-to-your-testSlice"; // 导入正确的action export default function MenuComponents () { const { open, name } = useSelector((state: RootState) => state.testDialog ); const dispatch = useDispatch(); return ( <Grid container spacing={2}> <Grid item xs={6}> <Typography variant={'subtitle2'}>Dialog 1</Typography> <IconButton onClick={() => dispatch(setOpenDialog('menuA'))} > <OpenInBrowser /> </IconButton> <Menu open={name === 'menuA' && open} onClose={() => dispatch(closeDialog())} // 绑定关闭逻辑 > <MenuItem>Option A</MenuItem> <MenuItem>Option B</MenuItem> <MenuItem>Option C</MenuItem> <MenuItem>Option D</MenuItem> <MenuItem>Option E</MenuItem> </Menu> </Grid> <Grid item xs={6}> <Typography variant={'subtitle2'}>Dialog 2</Typography> <IconButton onClick={() => dispatch(setOpenDialog('menuB'))} > <OpenInBrowser /> </IconButton> <Menu open={name === 'menuB' && open} onClose={() => dispatch(closeDialog())} // 绑定关闭逻辑 > <MenuItem>Option A</MenuItem> <MenuItem>Option B</MenuItem> <MenuItem>Option C</MenuItem> <MenuItem>Option D</MenuItem> <MenuItem>Option E</MenuItem> </Menu> </Grid> </Grid> ) }
补充建议
- 菜单关闭逻辑:通过
Menu组件的onClose事件触发closeDialogaction,重置open和name状态,避免菜单状态混乱。 - 状态判断优化:可以在Slice中新增一个selector,直接返回当前应该打开的菜单名称,减少组件中的逻辑判断,比如:
组件中使用时:export const selectCurrentOpenMenu = (state: RootState) => state.testDialog.open ? state.testDialog.name : null;const currentOpenMenu = useSelector(selectCurrentOpenMenu); // 菜单open属性改为:currentOpenMenu === 'menuA'
内容的提问来源于stack exchange,提问作者Himanshu Sharma
相关产品推荐
相关产品推荐

