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

React侧边栏菜单未按权限更新,仅热构建后生效问题排查

问题排查与修复方案

核心问题分析

  1. 顶层await语法错误
    你在data.jsx的对象字面量中直接使用await keycloakService.hasRole(...),这是非法语法——await只能在异步函数内部使用,导致visibility实际是一个未resolved的Promise对象,而非预期的'true'/'false'字符串。初始渲染时,itemData.visibility == 'true'的判断永远不成立,只有热更新时权限请求已完成,这个Promise被隐式处理后才会显示正确结果。

  2. 静态数组无法响应异步权限结果
    SIDEBAR_DATA是静态常量,初始化时keycloakService.hasRole的异步请求还未返回结果,因此visibility的初始值错误,无法动态更新视图。

  3. 数据引用不匹配
    SidebarItems.jsx中导入的是dummyData,但data.jsx导出的是SIDEBAR_DATA,这会导致渲染的不是你配置了权限的目标菜单数据。


修复代码

1. 重构data.jsx:定义基础菜单结构,剥离权限逻辑

import AdminPanelSettingsOutlined from "@mui/icons-material/AdminPanelSettingsOutlined";
import {
  HomeIcon,
  LayoutIcon,
  CalendarIcon,
  InvoiceIcon,
  UserIcon,
  RolesIcon,
  PagesIcon,
  AuthIcon,
  WizardIcon,
  ModalIcon,
} from "./Icons";

// 基础菜单数据,仅定义结构和权限要求,不做权限判断
export const BASE_SIDEBAR_DATA = [
  {
    id: 1,
    name: "Home",
    path: "/secured",
    icon: <HomeIcon/>,
    requiredRoles: [] // 无权限要求的菜单留空数组
  },
  {
    id: 2,
    name: "Administration",
    path: "/Administration",
    icon: <AdminPanelSettingsOutlined/>,
    requiredRoles: ['NexaAdmin'] // 指定需要的角色
  },
];

2. 修改SidebarItems.jsx:异步获取权限,动态生成可显示菜单

import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import {
  ItemsList,
  ItemContainer,
  ItemWrapper,
  ItemName,
} from "./SidebarStyles";

import { BASE_SIDEBAR_DATA } from "./data"; // 导入基础菜单数据
import keycloakService from "../KeycloakService";

const SidebarItems = ({ displaySidebar }) => {
  const [activeItem, setActiveItem] = useState(0);
  const [visibleMenuItems, setVisibleMenuItems] = useState([]);

  useEffect(() => {
    // 异步获取权限,过滤可显示菜单
    const fetchVisibleMenus = async () => {
      const visibleItems = await Promise.all(
        BASE_SIDEBAR_DATA.map(async (item) => {
          // 无权限要求的直接显示,否则检查角色
          if (item.requiredRoles.length === 0) {
            return item;
          }
          const hasPermission = await keycloakService.hasRole(item.requiredRoles);
          return hasPermission ? item : null;
        })
      );
      // 过滤掉无权限的菜单
      setVisibleMenuItems(visibleItems.filter(Boolean));
    };

    fetchVisibleMenus();

    // 监听keycloak状态变化,用户身份变更时自动更新菜单
    const keycloakListener = keycloakService.onAuthStateChanged(() => {
      fetchVisibleMenus();
    });

    return () => keycloakListener?.unsubscribe();
  }, []);

  return (
    <ItemsList>
      {visibleMenuItems.map((itemData) => (
        <ItemContainer
          key={itemData.id}
          onClick={() => setActiveItem(itemData.id)}
          className={itemData.id === activeItem ? "active" : ""}
        >
          <Link to={itemData.path}>
            <ItemWrapper>
              {itemData.icon}
              <ItemName displaySidebar={displaySidebar}>
                {itemData.name}
              </ItemName>
            </ItemWrapper>
          </Link>
        </ItemContainer>
      ))}
    </ItemsList>
  );
};

export default SidebarItems;

关键修复点说明

  • 把权限判断从静态数组移到组件的useEffect中,利用异步函数正确获取keycloak权限结果
  • 通过useState维护可显示菜单列表,权限结果返回后自动触发视图更新
  • 增加keycloak状态监听,确保用户登录/登出或角色变更时,菜单权限能同步更新
  • 修正了数据引用错误,确保使用正确的基础菜单数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:09:53