简体   繁体   English

如何在 React.js 的数组中放置受保护的路由?

[英]How to place protected routes within an array in React.js?

I'm hoping to set up protected routes for my webapp built with React.js.我希望为我用 React.js 构建的 webapp 设置受保护的路由。 I have an array 'menuOptions' that I have been looping through to add options to my navbar.我有一个数组'menuOptions',我一直在循环向我的导航栏添加选项。 However, I've now been running in to issues as I would like to add protected routes.但是,我现在遇到了一些问题,因为我想添加受保护的路由。

So for instance, I would like to have Home, Login and Register when the user is logged out, and Dashboard and Logout as the options for when the user is logged in. I'd really appreciate any help.因此,例如,我希望在用户注销时拥有 Home、Login 和 Register,以及 Dashboard 和 Logout 作为用户登录时的选项。我非常感谢任何帮助。 Ideally, I'd somehow add the '.user' to the menuOptions array somehow.理想情况下,我会以某种方式将“.user”添加到 menuOptions 数组中。

My code is below (as you can see menuOptions does not do anything for the above at the moment):我的代码如下(您可以看到 menuOptions 目前对上述内容没有任何作用):

import React, { useState, useContext } from "react";
import { Link, NavLink, useNavigate } from "react-router-dom";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, logout } from "../../firebase";
import { makeStyles } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import IconButton from "@material-ui/core/IconButton";
import MenuIcon from "@material-ui/icons/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import Menu from "@material-ui/core/Menu";
import { useTheme } from "@material-ui/core/styles";
import useMediaQuery from "@material-ui/core/useMediaQuery";

const useStyles = makeStyles((theme) => ({
  title: {
    flexGrow: 1,
  },
  appbar: {
    // background: 'none',
  },
  inactiveLink: {
    color: "white",
    padding: theme.spacing(1),
    fontSize: "1.5rem",
  },
  activeLink: {
    color: "black",
    padding: theme.spacing(1),
    fontSize: "1.5rem",
    background: "#bfbfbf",
  },
}));

function Navigation() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = useState(null);
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("md"));

  const open = Boolean(anchorEl);
  const menuOptions = [
    { label: "Home", path: "/",  },
    { label: "Register", path: "/register" },
    { label: "Dashboard", path: "/dashboard" },
    { label: "Logout", path: "/logout" },
  ];

  const handleMenuSelect = (pageURL) => {
    navigate(pageURL);
  };

  const handleMenu = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const [user] = useAuthState(auth);
  const navigate = useNavigate();
  return (
    <>
      <AppBar
        className={classes.appbar}
        position="fixed"
        elevation={0}
        color="primary"
      >
        <Toolbar>
          <Typography variant="h4" className={classes.title}>
            The Football App
          </Typography>
          <Typography variant="h6" className={classes.title}>
            All you ever wanted to know about Football!
          </Typography>
          {isMobile ? (
            <>
              <IconButton
                aria-label="menu"
                aria-controls="menu-appbar"
                aria-haspopup="true"
                onClick={handleMenu}
                color="inherit"
              >
                <MenuIcon />
              </IconButton>
              <Menu
                id="menu-appbar"
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: "top",
                  horizontal: "right",
                }}
                keepMounted
                transformOrigin={{
                  vertical: "top",
                  horizontal: "right",
                }}
                open={open}
                onClose={() => setAnchorEl(null)}
              >
                {menuOptions.map((opt) => (
                  <MenuItem
                    key={opt.label}
                    onClick={() => handleMenuSelect(opt.path)}
                  >
                    {opt.label}
                  </MenuItem>
                ))}
              </Menu>
            </>
          ) : (
            <>
              <nav>
                <div>
                  {!user ? (
                    <NavLink
                      to="/"
                      className={({ isActive }) =>
                        isActive
                      }
                    >
                      Home
                    </NavLink>
                  ) : (
                    <NavLink
                      to="/dashboard"
                      className={({ isActive }) =>
                        isActive
                      }
                    >
                      Dashboard
                    </NavLink>
                  )}
                </div>
                {!user ? (
                  <div>
                    <Link to="/login">
                      <a>Login</a>
                    </Link>
                    <Link to="/register">
                      <a>Register</a>
                    </Link>
                    </div>
                ) : (
                  <div className="navbar-end">
                    <Link to="/logout">
                      <a>Log Out</a>
                    </Link>
                  </div>
                )}
              </nav>
            </>
          )}
        </Toolbar>
      </AppBar>
    </>
  );
}

export default Navigation;

You could update your menuOptions object to include a protected key:您可以更新menuOptions object 以包含protected的密钥:

const menuOptions = [
    { label: "Home", path: "/", protected:  false },
    { label: "Register", path: "/register", protected:  false },
    { label: "Dashboard", path: "/dashboard", protected:  false },
    { label: "Logout", path: "/logout", protected:  true },
  ];

and update the logic where your render your menu options to something like并将您的菜单选项呈现为类似的逻辑更新

{menuOptions.map((opt) => {
  if (opt.protected && !user) return;
  return (
    <MenuItem
      key={opt.label}
      onClick={() => handleMenuSelect(opt.path)}
    >
      {opt.label}
    </MenuItem>
  );
}
)}

to only show certain options if the user exists仅在用户存在时显示某些选项

{menuOptions.filter((opt) => (user ? opt.protected : !opt.protected)).map((opt) =>  (
    <MenuItem
      key={opt.label}
      onClick={() => handleMenuSelect(opt.path)}
    >
      {opt.label}
    </MenuItem>
  )
)}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM