我正在开发一个React应用,它有不同的用户类型。每个用户的菜单上都有特定的项。项可以是链接或子菜单。我想为链接项呈现按钮,为子菜单呈现折叠(react-bootstrap的)。但是,为了让Collapse正常工作,我需要在每个子菜单项上添加一个布尔状态。
所有菜单都在一个文件中分开,如下所示:
// /utils/Menus.js
export const AdminMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "Users", href: "#", subitems: [
{ label: "All Users", href: "/users" },
{ label: "New User", href: "/users/new" }
] },
{ label: "Products", href: "#", subitems: [
{ label: "All Products", href: "/products" },
{ label: "New Product", href: "/products/new" }
] },
{ label: "Clients", href: "#", subitems: [
{ label: "All Clients", href: "/clients" },
{ label: "New Client", href: "/clients/new" }
] },
{ label: "Orders", href: "/orders", subitems: [
{ label: "All Orders", href: "/orders" },
{ label: "Cancelled", href: "/orders/cancelled" },
{ label: "Latest", href: "/orders/latest" }
] },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
export const ClientMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "My Orders", href: "/orders" },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
export const ManagerMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "Products", href: "#", subitems: [
{ label: "All Products", href: "/products" },
{ label: "New Product", href: "/products/new" }
] },
{ label: "Orders", href: "/orders", subitems: [
{ label: "All Orders", href: "/orders" },
{ label: "Cancelled", href: "/orders/cancelled" },
{ label: "Latest", href: "/orders/latest" }
] },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
我有一个侧边栏组件,它根据登录的用户配置文件呈现菜单。在这个组件上,我想在每个具有subitems
属性的菜单项上添加一个open
状态属性。这样:
// /components/Sidenav.js
[...]
const [userMenu, setUserMenu] = useState([]);
useEffect(() => {
let menu = [];
switch(user.role){
case "admin":
menu = [...AdminMenu];
break;
case "client":
menu = [...ClientMenu];
break;
case "manager":
menu = [...ManagerMenu];
break;
}
menu = menu.map((item) => {
if(item.subitems){
item = {...item, open: useState(false)}
}
return item;
});
setUserMenu(menu);
}, []);
return (
<ul>
{userMenu.map((item, i) => (
<li key={i}>
{ item.subitems ? (
<>
<button onClick={() => { item.open[1](!item.open[0]) }}>{item.label}</button>
<Collapse in={item.open[0]}>\
<ul>
{ item.subitems.map((subitem, j) => (
<li key={j}>
<Link href={subitem.href}>{subitem.label}</Link>
</li>
)) }
</ul>
</Collapse>
</>
) : (
<Link href={item.href}>{item.label}</Link>
) }
</li>
))}
</ul>
);
因此,方法是尝试在每个有子项的项上动态添加open
状态。并且,在渲染时,使用item.open[0]
(状态)和item.open[1]
(设置状态函数)来切换Collapse的状态。
问题是:React抛出了一个错误,说我不能在函数组件之外使用useState
,但是当我在项目上添加open
属性时,我在函数组件上的useEffect
中,那么问题在哪里呢?
我已经测试了将组件上的菜单声明为常量,并在必要时直接属性化open
状态,它按预期工作。
// /components/Sidenav.js
[...]
const [userMenu, setUserMenu] = useState([]);
const AdminMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "Users", href: "#", open: useState(false), subitems: [
{ label: "All Users", href: "/users" },
{ label: "New User", href: "/users/new" }
] },
{ label: "Products", href: "#", open: useState(false), subitems: [
{ label: "All Products", href: "/products" },
{ label: "New Product", href: "/products/new" }
] },
{ label: "Clients", href: "#", open: useState(false), subitems: [
{ label: "All Clients", href: "/clients" },
{ label: "New Client", href: "/clients/new" }
] },
{ label: "Orders", href: "/orders", open: useState(false), subitems: [
{ label: "All Orders", href: "/orders" },
{ label: "Cancelled", href: "/orders/cancelled" },
{ label: "Latest", href: "/orders/latest" }
] },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
const ClientMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "My Orders", href: "/orders" },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
const ManagerMenu = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "Products", href: "#", open: useState(false), subitems: [
{ label: "All Products", href: "/products" },
{ label: "New Product", href: "/products/new" }
] },
{ label: "Orders", href: "/orders", open: useState(false), subitems: [
{ label: "All Orders", href: "/orders" },
{ label: "Cancelled", href: "/orders/cancelled" },
{ label: "Latest", href: "/orders/latest" }
] },
{ label: "My Profile", href: "/my-profile" },
{ label: "Logout", href: "/logout" }
];
useEffect(() => {
switch(user.role){
case "admin":
setUserMenu(AdminMenu);
break;
case "client":
setUserMenu(ClientMenu);
break;
case "manager":
setUserMenu(ManagerMenu);
break;
}
}, []);
return (
[...]
);
但是这使得我在显示用户菜单时需要重复菜单常量,这不是最好的方法。
那么,如何在菜单项上添加open
状态,以动态呈现链接或折叠?
1条答案
按热度按时间g52tjvyc1#
我认为将其作为一个组件会更简单一些,其状态如下(我在下面自由排版,所以代码可能无法正常工作)