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

React/MUI导航栏Menu/MenuItem跳转异常,如何正确分离配置?

导航栏多Menu/MenuItem跳转异常问题解决

问题描述

开发React应用导航栏时,Movies和Actors的下拉菜单选项均跳转至同一页面(初始为/actors),尝试为两个菜单创建独立的anchorEl、open状态及处理函数后,问题反转成两个菜单都跳转至/movies页面。

问题代码

import { useState } from 'react';import { Link, useNavigate } from 'react-router-dom';import Grid from '@mui/material/Grid';import Button from '@mui/material/Button';import Menu from '@mui/material/Menu';import MenuItem from '@mui/material/MenuItem'; 
const Navbar = (props) => {    const navigate = useNavigate();
    const logout = () => {        props.onAuthenticated(false);        navigate('/');    };
    const [anchorEl, setAnchorEl] = useState(null);    const open = Boolean(anchorEl);
    const handleClick = (event) => {      setAnchorEl(event.currentTarget);    };
    const handleClose = () => {      setAnchorEl(null);    };
    return (        <Grid item xs={12}>            <Button component={Link} to='/'>Home</Button>            <Button                id="basic-button-1"                aria-controls={open ? 'basic-menu-1' : undefined}                aria-haspopup="true"                aria-expanded={open ? 'true' : undefined}                onClick={handleClick}            >                Movies            </Button>            <Button                id="basic-button-2"                aria-controls={open ? 'basic-menu-2' : undefined}                aria-haspopup="true"                aria-expanded={open ? 'true' : undefined}                onClick={handleClick}            >                Actors            </Button>            <Menu                id="basic-menu-1"                anchorEl={anchorEl}                open={open}                onClose={handleClose}                MenuListProps={{                'aria-labelledby': 'basic-button-1',                }}            >                <MenuItem component={Link} to='/movies' onClick={handleClose}>All</MenuItem>                <MenuItem component={Link} to='/movies/create' onClick={handleClose}>Create</MenuItem>            </Menu>            <Menu                id="basic-menu-2"                anchorEl={anchorEl}                open={open}                onClose={handleClose}                MenuListProps={{                'aria-labelledby': 'basic-button-2',                }}            >                <MenuItem component={Link} to='/actors' onClick={handleClose}>All</MenuItem>                <MenuItem component={Link} to='/actors/create' onClick={handleClose}>Create</MenuItem>            </Menu>
            {(props.authenticated) ? (                <Button variant='outlined' onClick={logout}>Logout</Button>            ) : ""}
        </Grid>    );};
export default Navbar;

问题原因

两个Menu共享同一个anchorEl和open状态,点击任意按钮时两个Menu都会被标记为open。React渲染时后一个Menu(Actors的Menu)会覆盖前一个,导致点击时实际触发的是后一个Menu的跳转链接;分开状态后反转问题,是因为处理函数与状态的对应关系错误,导致菜单激活逻辑混乱。

解决方案

新增状态跟踪当前激活的菜单ID,精确控制单个菜单的显示/隐藏:

import { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import Grid from '@mui/material/Grid';
import Button from '@mui/material/Button';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem'; 

const Navbar = (props) => {    
    const navigate = useNavigate();

    const logout = () => {        
        props.onAuthenticated(false);        
        navigate('/');    
    };

    // 用activeMenuId跟踪当前打开的菜单标识
    const [anchorEl, setAnchorEl] = useState(null);
    const [activeMenuId, setActiveMenuId] = useState(null);
    const open = Boolean(anchorEl);

    const handleClick = (event, menuId) => {
        setAnchorEl(event.currentTarget);
        setActiveMenuId(menuId);
    };

    const handleClose = () => {
        setAnchorEl(null);
        setActiveMenuId(null);
    };

    return (        
        <Grid item xs={12}>            
            <Button component={Link} to='/'>Home</Button>            
            <Button                
                id="basic-button-1"                
                aria-controls={open && activeMenuId === 'movies' ? 'basic-menu-1' : undefined}                
                aria-haspopup="true"                
                aria-expanded={open && activeMenuId === 'movies' ? 'true' : undefined}                
                onClick={(e) => handleClick(e, 'movies')}            
            >                
                Movies            
            </Button>            
            <Button                
                id="basic-button-2"                
                aria-controls={open && activeMenuId === 'actors' ? 'basic-menu-2' : undefined}                
                aria-haspopup="true"                
                aria-expanded={open && activeMenuId === 'actors' ? 'true' : undefined}                
                onClick={(e) => handleClick(e, 'actors')}            
            >                
                Actors            
            </Button>            
            <Menu                
                id="basic-menu-1"                
                anchorEl={anchorEl}                
                open={open && activeMenuId === 'movies'}                
                onClose={handleClose}                
                MenuListProps={{                    
                    'aria-labelledby': 'basic-button-1',                
                }}            
            >                
                <MenuItem component={Link} to='/movies' onClick={handleClose}>All</MenuItem>                
                <MenuItem component={Link} to='/movies/create' onClick={handleClose}>Create</MenuItem>            
            </Menu>            
            <Menu                
                id="basic-menu-2"                
                anchorEl={anchorEl}                
                open={open && activeMenuId === 'actors'}                
                onClose={handleClose}                
                MenuListProps={{                    
                    'aria-labelledby': 'basic-button-2',                
                }}            
            >                
                <MenuItem component={Link} to='/actors' onClick={handleClose}>All</MenuItem>                
                <MenuItem component={Link} to='/actors/create' onClick={handleClose}>Create</MenuItem>            
            </Menu>

            {props.authenticated && (                
                <Button variant='outlined' onClick={logout}>Logout</Button>            
            )}        
        </Grid>    
    );
};

export default Navbar;

关键修改点

  • 新增activeMenuId状态,标记当前打开的菜单('movies'或'actors')
  • handleClick函数新增menuId参数,点击时记录激活的菜单ID
  • 每个Menu的open属性改为open && activeMenuId === 对应ID,确保仅目标菜单打开
  • 调整aria-controls和aria-expanded的判断逻辑,仅针对激活的菜单生效
  • 简化Logout条件渲染,用&&替代冗余的三元表达式

内容的提问来源于stack exchange,提问作者Marcus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:05:23