You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数处理错误:setOpenDialog reducer中,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事件触发closeDialog action,重置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:45:29