我正在尝试实现一个动态菜单,该菜单会根据用户角色来更改其结构
查看下面的完整代码:
import React, {
useState,
useLayoutEffect,
useEffect,
useCallback,
} from "react";
import { Drawer, IconButton, List, Avatar } from "@material-ui/core";
import {
Inbox as InboxIcon,
PresentToAll as PresentToAllIcon,
ListAlt as ListAltIcon,
Language as LanguageIcon,
Description as DescriptionIcon,
List as ListIcon,
Money as MoneyIcon,
Face as FaceIcon,
TransferWithinAStation as TransferWithinAStationIcon,
AttachMoney as AttachMoneyIcon,
PersonPinCircle as PersonPinCircleIcon,
Home as HomeIcon,
ArrowBack as ArrowBackIcon,
Edit as EditIcon,
AccountBalanceWallet,
PeopleAlt,
} from "@material-ui/icons";
import { useTheme } from "@material-ui/styles";
import { withRouter } from "react-router-dom";
import classNames from "classnames";
import useStyles from "./styles";
import SidebarLink from "./components/SidebarLink/SidebarLink";
import {
useLayoutState,
useLayoutDispatch,
toggleSidebar,
} from "../../context/LayoutContext";
import Dot from "./components/Dot";
import pesonetlogo from "../../images/test-logo.png";
import { USER_PROFILE_ID_SESSION_ATTRIBUTE } from "../../services/AuthenticationService";
import ProfileMaintenanceService from "../../services/ProfileMaintenanceService";
function Sidebar({ location }) {
var classes = useStyles();
var theme = useTheme();
var { isSidebarOpened, modules } = useLayoutState();
var layoutDispatch = useLayoutDispatch();
var [isPermanent, setPermanent] = useState(true);
// should be in UserContext for global state
const [profileDetails, setProfileDetails] = useState([]);
const [profileModules, setProfileModules] = useState([]);
// const [profileActions, setProfileActions] = useState([]);
var structureNew = [];
const profileList = sessionStorage.getItem(USER_PROFILE_ID_SESSION_ATTRIBUTE);
useEffect(() => {
modules.forEach((modulesMap, i) => {
structureNew[i] = structure.filter(
(structureFiltered) => structureFiltered.label == modulesMap
);
});
console.log("06262020 useEffect structureNew ", structureNew)
}, []);
// useLayoutEffect(() => {
// console.log("06252020 useEffect profileDetails ", profileDetails);
// const modules = profileDetails.map((module) => module.module);
// // const actions = profileDetails
// // .map((item) => item.actions.map((action) => action.action))
// // .flat();
// setProfileModules(profileModules.concat(modules));
// // setProfileActions(profileActions.concat(actions));
// }, [profileDetails]);
// useLayoutEffect(() => {
// console.log("06252020 useEffect profileModules ", profileModules);
// structureNew = structure.filter(
// (structureFiltered) => structureFiltered.label == "Inward"
// );
// console.log("06252020 structureNew ", structureNew);
// }, [profileModules]);
// // // should be in UserContext for global use
// const retrieveProfileDetails = useCallback(() => {
// const profileListArr = profileList.split(",");
// profileListArr.forEach((profileListArrMap) => {
// ProfileMaintenanceService.retrieveProfileDetails(profileListArrMap).then(
// // dapat makuha din menu?
// (response) => {
// console.log(
// "06252020 retrieveProfileDetails response.data ",
// response.data
// );
// setProfileDetails(response.data);
// }
// );
// });
// });
var structure = [
{ id: 0, label: "Dashboard", link: "/test/dashboard", icon: <HomeIcon /> },
{
id: 1,
label: "Test1",
link: "/test1",
icon: <InboxIcon />,
},
{
id: 2,
label: "Test2",
link: "/test2",
icon: <PresentToAllIcon />,
},
{ id: 3, type: "divider" },
{
id: 4,
label: "Test3",
link: "/test3",
icon: <ListAltIcon />,
children: [
{
label: "Test4",
link: "/test4",
icon: <LanguageIcon />,
},
{
label: "Test5",
link: "/test5",
icon: <ListIcon />,
},
],
},
{
id: 5,
label: "Test6",
link: "/test6",
icon: <DescriptionIcon />,
},
{
id: 6,
label: "Test7",
link: "/test7",
icon: <AccountBalanceWallet />,
children: [
{
label: "Test8",
link: "/test8",
icon: <FaceIcon />,
},
{
label: "Test9",
link: "/test9",
icon: <TransferWithinAStationIcon />,
},
{
label: "Test10",
link: "/test10",
icon: (
<Avatar alt="Pesonet" src={pesonetlogo} className={classes.small} />
),
},
{
label: "Test11",
link: "/test11",
icon: <PeopleAlt />,
},
],
},
{
id: 7,
label: "Test12",
link: "/test12",
icon: <EditIcon />,
},
];
useEffect(function() {
window.addEventListener("resize", handleWindowWidthChange);
handleWindowWidthChange();
return function cleanup() {
window.removeEventListener("resize", handleWindowWidthChange);
};
});
return (
<Drawer
variant={isPermanent ? "permanent" : "temporary"}
className={classNames(classes.drawer, {
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
})}
classes={{
paper: classNames({
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
}),
}}
open={isSidebarOpened}
>
<div className={classes.toolbar} />
<div className={classes.mobileBackButton}>
<IconButton onClick={() => toggleSidebar(layoutDispatch)}>
<ArrowBackIcon
classes={{
root: classNames(classes.headerIcon, classes.headerIconCollapse),
}}
/>
</IconButton>
</div>
<List className={classes.sidebarList}>
{structureNew.map((link) => (
<SidebarLink
key={link.id}
location={location}
isSidebarOpened={isSidebarOpened}
{...link}
/>
))}
</List>
</Drawer>
);
function handleWindowWidthChange() {
var windowWidth = window.innerWidth;
var breakpointWidth = theme.breakpoints.values.md;
var isSmallScreen = windowWidth < breakpointWidth;
if (isSmallScreen && isPermanent) {
setPermanent(false);
} else if (!isSmallScreen && !isPermanent) {
setPermanent(true);
}
}
}
export default withRouter(Sidebar);
如您所见,structureNew
包含经过一些数组操作在useEffect
中形成的菜单和子菜单
但是,我的问题是页面首先被渲染并调用structureNew
。此时,structureNew
为空
我希望在呈现页面之前先形成structureNew
有什么办法可以使用钩子吗?
TIA
答案 0 :(得分:1)
为什么不创建一个structureNew
作为State并在该useEffect中设置setStructureNew?
答案 1 :(得分:1)
我建议添加一个加载器,例如:
const [loading, setLoading] = useState(true)
然后在进行操作后将加载设置为false:
setLoading(false)
并且在添加返回之前:
if(loading){
return(<LoaderComponent/>)
}
return(
//your main return
)