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

React侧边栏:点击子菜单时父菜单意外折叠/闪烁的解决方案咨询

React侧边栏:点击子菜单时父菜单意外折叠/闪烁的解决方案咨询

嘿,我最近在React里实现一个带可展开菜单和子菜单的侧边栏,用openMenus对象管理菜单的展开状态,导航部分依赖react-router-dom。现在遇到个挺烦人的问题:父菜单点击展开完全正常,但点击子菜单跳转到其他路由时,父菜单会先折叠再快速展开,出现明显的闪烁效果。

我试过用useEffect监听location.pathname,当路由匹配到某个子菜单时自动打开对应的父菜单,但这好像触发了状态重置的问题——每次导航都会重新处理菜单状态,这应该就是导致闪烁的原因。

我想要实现的效果是:点击子菜单完成导航后,对应的父菜单保持打开状态,不会出现折叠/闪烁的情况,同时用户仍然可以手动关闭这个父菜单。有没有大佬能给点实用的建议或者代码示例,讲讲在React侧边栏里结合react-router-dom正确处理这种导航和状态的模式呀?非常感谢!

以下是我当前的代码:

import React, { useState, useEffect } from "react";
import { Link, useLocation } from "react-router-dom";
import { 
  Home, Package, ShoppingCart, BarChart2, Settings, 
  ChevronDown, ChevronUp, Users, LifeBuoy, Activity, Truck 
} from "lucide-react";

// 增强版菜单结构
const menuStructure = [
  { 
    name: "Punto de Venta", 
    icon: <ShoppingCart className="w-6 h-6" />, 
    submenus: [
      { name: "Nueva Venta", path: "/ventas" },
      { name: "Ventas Rápidas", path: "/ventas-rapidas" },
      { name: "Ventas Pendientes", path: "/ventas-pendientes", badge: "ventasPendientes" },
      { name: "Caja", path: "/caja" },
      { name: "Turnos", path: "/turnos" },
      { name: "Promociones", path: "/venta/promociones" },
      { name: "Modo TPV", path: "/tpv" }
    ] 
  },
  { 
    name: "Operaciones", 
    icon: <Activity className="w-6 h-6" />, 
    submenus: [
      { name: "Ventas", path: "/operaciones/ventas" },
      { name: "Compras", path: "/operaciones/compras" },
      { name: "Transferencias", path: "/operaciones/transferencias" },
      { name: "Devoluciones", path: "/operaciones/devoluciones" },
      { name: "Cortes Z/X", path: "/operaciones/cortes" },
      { name: "Cierre Diario", path: "/operaciones/cierre", shortcut: "Ctrl+L" }
    ] 
  },
  { 
    name: "Inventario", 
    icon: <Package className="w-6 h-6" />, 
    submenus: [
      { name: "Productos", path: "/productos" },
      { name: "Categorías", path: "/categorias" },
      { name: "Almacenes", path: "/almacenes" },
      { name: "Movimientos", path: "/inventario/movimientos" },
      { name: "Stock Crítico", path: "/inventario/stock-critico", badge: "stockCritico" },
      { name: "Lotes/Series", path: "/inventario/lotes" },
      { name: "Importar/Exportar", path: "/inventario/importar" },
      { name: "Unidades", path: "/unidades" },
      { name: "Grupos", path: "/grupos" },
      { name: "Marcas", path: "/marcas" },
      { name: "Estados", path: "/estados" },
    ] 
  },
  { 
    name: "Clientes", 
    icon: <Users className="w-6 h-6" />, 
    submenus: [
      { name: "Lista de Clientes", path: "/clientes" },
      { name: "Nuevo Cliente", path: "/clientes/nuevo" },
      { name: "Segmentos", path: "/segmentos-clientes" },
      { name: "Programa de Fidelidad", path: "/clientes/fidelidad" },
      { name: "Cartera", path: "/clientes/cartera" },
      { name: "Comunicación", path: "/clientes/comunicacion" },
      { name: "Tipos de Documento", path: "/tipos-documento" },
    ] 
  },
  { 
    name: "Proveedores", 
    icon: <Truck className="w-6 h-6" />, 
    submenus: [
      { name: "Lista de Proveedores", path: "/proveedores" },
      { name: "Órdenes de Compra", path: "/ordenes-compra" },
      { name: "Histórico de Precios", path: "/proveedores/precios" },
      { name: "Evaluación", path: "/proveedores/evaluacion" },
      { name: "Pagos", path: "/proveedores/pagos" },
      { name: "Contratos", path: "/proveedores/contratos" }
    ] 
  },
  { 
    name: "Reportes", 
    icon: <BarChart2 className="w-6 h-6" />, 
    submenus: [
      { name: "Dashboard", path: "/dashboard" },
      { name: "Ventas", path: "/reportes/ventas" },
      { name: "Productos", path: "/reportes/productos" },
      { name: "Clientes", path: "/reportes/clientes" },
      { name: "Caja", path: "/reportes/caja" },
      { name: "Inventario", path: "/reportes/inventario" },
      { name: "Comparativos", path: "/reportes/comparativos" }
    ] 
  },
  { 
    name: "Administración", 
    icon: <Settings className="w-6 h-6" />, 
    submenus: [
      { name: "Usuarios", path: "/usuarios" },
      { name: "Terminales", path: "/admin/terminales" },
      { name: "Impuestos", path: "/admin/impuestos" },
      { name: "Formas de Pago", path: "/admin/pagos" },
      { name: "Personalización", path: "/admin/personalizacion" },
      { name: "Backup", path: "/admin/backup" },
      { name: "API", path: "/admin/api" }
    ] 
  },
  { 
    name: "Soporte", 
    icon: <LifeBuoy className="w-6 h-6" />, 
    submenus: [
      { name: "Manuales", path: "/soporte/manuales" },
      { name: "Soporte Técnico", path: "/soporte/contacto" },
      { name: "Actualizaciones", path: "/soporte/actualizaciones", badge: "actualizaciones" },
      { name: "Diagnóstico", path: "/soporte/diagnostico" },
      { name: "Legal", path: "/soporte/legal" }
    ] 
  }
];

const Sidebar = ({ isSidebarExpanded, userRoles = [], badges = {} }) => {
  const [openMenus, setOpenMenus] = useState({});
  const location = useLocation();

  // 这里省略了处理菜单展开/折叠和路由匹配的逻辑
};

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:18:06