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
相关产品推荐
相关产品推荐

