【问题标题】:Highlighting Menus in React在 React 中突出显示菜单
【发布时间】:2020-10-02 08:47:57
【问题描述】:

我已经在 React 中实现了一个菜单项,并且如果菜单位于该特定 URL 上,我已经成功突出显示。我的问题是当我在那个菜单的内部时。例如,我有一个名为“待处理订单”的菜单,它突出显示,而如果我在“待处理订单视图”上,突出显示的部分会消失。我认为它在此代码selected={location.pathname === obj.url} 上。解决此问题的最佳方法是什么?

SideNav

  function SideNav(props) {
  const { window, location } = props;
  const classes = useStyles();
  const theme = useTheme();
  const [mobileOpen, setMobileOpen] = React.useState(false);
  const [loggedOut, isLoggingOut] = React.useState(false);
  const dispatch = useDispatch();
  const history = useHistory();
  const isStaff = useSelector((state) => state.auth.is_staff);
  const firstName = useSelector((state) => state.auth.first_name);
  const lastName = useSelector((state) => state.auth.last_name);
  const [openMenuID, setOpenMenuID] = React.useState(null);
  const [open, setLogoutDialogOpen] = React.useState(false);

  const openLogoutDialog = () => {
    setLogoutDialogOpen(true);
  };

  const closeLogoutDialog = () => {
    setLogoutDialogOpen(false);
  };

  const toggleOpenMenu = (menuId) => {
    if (openMenuID === menuId) {
      setOpenMenuID(null);
    } else {
      setOpenMenuID(menuId);
    }
  };

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const signOut = () => {
    dispatch(logout());
    isLoggingOut(true);
  };

  if (loggedOut) {
    return <Redirect to={{ pathname: '/login', state: { referer: props.location } }} />;
  }

  const menuItems = [
    {
      id: 1,
      text: 'Orders',
      submenu: [
        {
          id: 1.1,
          text: 'Pending',
          url: '/orders/pending',
        },
        {
          id: 1.2,
          text: 'Approved',
          url: '/orders/approved',
        },
        {
          id: 1.3,
          text: 'Declined',
          url: '/orders/declined'
        },
      ],
    },
    {
      id: 2,
      text: 'Registration',
      url: `/registration`
    }
  ].map((obj, index) =>
    (obj.userAccess === false && isStaff) || obj.userAccess === true ? (
      <React.Fragment key={index}>
        <ListItem
          button
          selected={location.pathname === obj.url}
          key={obj.id}
          onClick={() => {
            if (obj.submenu) {
              toggleOpenMenu(obj.id);
            } else {
              setOpenMenuID(null);
              setMobileOpen(false);
              props.history.push(obj.url);
            }
          }}
        >
          <ListItemIcon>{obj.icon}</ListItemIcon>
          <ListItemText
            disableTypography
            primary={
              <Typography type="body1" style={{ color: '#FFFFFF' }}>
                {obj.text}
              </Typography>
            }
          />
          {obj.submenu ? openMenuID === obj.id ? <ExpandLessIcon /> : <ExpandMoreIcon /> : null}
        </ListItem>
        {obj.submenu ? (
          <Collapse in={openMenuID === obj.id} timeout="auto" unmountOnExit>
            <List component="div" disablePadding>
              {obj.submenu.map((subobj, index) => (
                <ListItem
                  selected={location.pathname === subobj.url}
                  button
                  key={subobj.id}
                  className={classes.nested}
                  onClick={() => {
                    setMobileOpen(false);
                    props.history.push(subobj.url);
                  }}
                >
                  <ListItemIcon>{subobj.icon}</ListItemIcon>
                  <ListItemText
                    disableTypography
                    primary={
                      <Typography type="body1" style={{ color: '#FFFFFF' }}>
                        {subobj.text}
                      </Typography>
                    }
                  />
                </ListItem>
              ))}
            </List>
          </Collapse>
        ) : null}
      </React.Fragment>
    ) : (
      ''
    )
  );

  const drawer = (
    <div>
      <Divider />
      <div className={classes.headerIcon}>
        <AccountCircleIcon fontSize="large" />
      </div>
      <h2 className={classes.headerName}>
        {firstName ? firstName : 'no name'} {lastName ? lastName : ''}
      </h2>
      <p className={classes.headerRole}>{isStaff ? 'Admin' : 'User'}</p>
      <Divider />
      <List>{menuItems}</List>
      <Divider />
    </div>
  );

  const container = window !== undefined ? () => window().document.body : undefined;

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar position="fixed" className={classes.appBar}>
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            edge="start"
            onClick={handleDrawerToggle}
            className={classes.menuButton}
          >
            <MenuIcon />
          </IconButton>
        </Toolbar>
      </AppBar>
      <nav className={classes.drawer} aria-label="mailbox folders">
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true,
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
    </div>
  );
}

SideNav.propTypes = {
  window: PropTypes.func,
};

export default withRouter(SideNav);

菜单

<ListItem
  button
  selected={location.pathname === obj.url}
  key={obj.id}
  onClick={() => {
    if (obj.submenu) {
      toggleOpenMenu(obj.id);
    } else {
      setOpenMenuID(null);
      setMobileOpen(false);
      props.history.push(obj.url);
    }
  }}
></ListItem>;

路线

<Switch>
  <PrivateRoute
    path={`${url}orders/approved/:id`}
    component={ViewOrder}
  />
  <PrivateRoute
    path={`${url}orders/approved`}
    component={ApprovedOrders}
  />
  <PrivateRoute
    path={`${url}orders/declined/:id`}
    component={ViewOrder}
  />
  <PrivateRoute
    path={`${url}orders/declined`}
    component={DeclinedOrders}
  />
  <PrivateRoute path={`${url}orders/new`} component={OrderForm} />
  <PrivateRoute
    path={`${url}orders/pending/:id`}
    component={ViewOrder}
  />
  <PrivateRoute
    path={[`${url}/`, `${url}orders/pending`]}
    component={PendingOrders}
  />
</Switch>;

【问题讨论】:

  • ListItem 在哪里渲染?
  • @RedBaron。就在&lt;React.Fragment&gt;里面
  • 你能展示那个组件吗
  • 谢谢。对不起,我真的很难想象这个。是否有机会展示您想要实现的目标以及当前实际发生的情况?
  • @RedBaron。如果我在挂单页面上,菜单会突出显示。问题出在这个-> 如果我在挂单视图页面上,菜单不再突出显示。这是清楚还是你想要一张照片?谢谢

标签: reactjs react-router react-hooks react-router-dom


【解决方案1】:

你说:

如果您使用的是Pending Orders page,它会突出显示,但如果您使用的是Pending Order View page,它就不会突出显示,对吧?

你的问题是这样的:location.pathname === obj.url 因为你正在寻找一个完全匹配,我认为它只发生在顶层

这个怎么样?

location.pathname.includes(obj.url) .includes() 将查找字符串的完整匹配项,因此您需要小心,但在这种情况下您可以只查找单词pending,它将匹配所有带有/pending 的路由在。

这是你想要的吗?

【讨论】:

  • 我认为location.pathname.includes(obj.url) 会更好,因为视图只添加/:id 对吗?顺便说一句,我们在子菜单上所以selected={location.pathname === subobj.url}
  • 我想我可能需要一张照片/图像才能完全理解是否可以:D
  • 我们会帮你搞定的。我试过这个location.pathname.includes(subjobj.url)
  • 你能帮我解决这个问题吗? stackoverflow.com/questions/62714769/…。谢谢
猜你喜欢
  • 2017-02-08
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-03
  • 2011-10-02
相关资源
最近更新 更多