[Snippet] - Authentication in React Router
React Router V5
file tree
.
├── conponents
    └── Authentication.tsx
├── pages
    ├── Home.tsx
    ├── Login.tsx
    └── Management.tsx
├── routes
    ├── privateRoutes.tsx
    └── publicRoutes.tsx
├── App.tsx
App.tsx
import React, { useState } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import publicRoutes from "./routes/publicRoutes";
import privateRoutes from "./routes/privateRoutes";
import Authentication from "./components/Authentication";
function App() {
  const [user, setUser] = useState({});
  const loginAsUser = () => {
    setUser({
      role: ["user"],
    });
  };
  return (
    <Router>
      <Switch>
        {publicRoutes.map(({ path, component: Component, ...route }) => (
          <Route
            key={path}
            path={path}
            render={(routeProps: any) => (
              <Component loginAsUser={loginAsUser} {...routeProps} />
            )}
            {...route}
          />
        ))}
        {privateRoutes.map((route) => (
          <Authentication key={route.path} {...route} user={user} />
        ))}
      </Switch>
    </Router>
  );
}
export default App;
publicRoutes.ts
import Login from "../pages/Login";
import Home from "../pages/Home";
const publicRoutes = [
  {
    path: "/login",
    component: Login,
    exact: true,
  },
  {
    path: "/",
    component: Home,
    exact: true,
  },
];
export default publicRoutes;
privateRoutes.ts
import Management from "../pages/Management";
const privateRoutes = [
  {
    path: "/management",
    component: Management,
    exact: true,
    role: "user",
    backUrl: "/login",
  },
];
export default privateRoutes;
Authentication.tsx
import React from "react";
import { Route, Redirect } from "react-router-dom";
function Authentication(props: any) {
  const {
    user: { role: userRole },
    role: routeRole,
    backUrl,
    ...otherProps
  } = props;
  // 如果用户有权限,就渲染对应的路由
  if (userRole && userRole.includes(routeRole)) {
    return <Route {...otherProps} />;
  } else {
    // 如果没有权限,返回配置的默认路由
    return <Redirect to={backUrl} />;
  }
}
export default Authentication;
注意:react-router-dom 所依赖的版本为 "^5.3.3",完整代码
React Router V6
file tree
├── conponents
    ├── AuthProvider.jsx
    ├── Navgation.jsx
    └── ProtectedRoute.tsx
├── hooks
    ├── useAuth.jsx
├── pages
    ├── Admin.jsx
    ├── Dashboard.jsx
    ├── Home.jsx
    └── NoMatch.jsx
├── stores
    ├── AuthContext.jsx
├── utils
    ├── fakeAuth.js
├── App.jsx
├── index.jsx
├── Router.jsx
App.jsx
import * as React from "react";
import AuthProvider from "./components/AuthProvider";
import Navigation from "./components/Navigation";
import Router from "./Router";
const App = () => {
  return (
    <AuthProvider>
      <h1>React Router V6</h1>
      <Navigation />
      <Router />
    </AuthProvider>
  );
};
export default App;
Router.jsx
import * as React from "react";
import { Routes, Route } from "react-router-dom";
import ProtectedRoute from "./components/ProtectedRoute";
import Home from "./pages/Home";
import Dashboard from "./pages/Dashboard";
import Admin from "./pages/Admin";
import NoMatch from "./pages/NoMatch";
const Router = () => {
  return (
    <Routes>
      <Route index element={<Home />} />
      <Route path="home" element={<Home />} />
      <Route
        path="dashboard"
        element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        }
      />
      <Route
        path="admin"
        element={
          <ProtectedRoute>
            <Admin />
          </ProtectedRoute>
        }
      />
      <Route path="*" element={<NoMatch />} />
    </Routes>
  );
};
export default Router;
AuthProvider.jsx
import * as React from "react";
import { useNavigate, useLocation } from "react-router-dom";
import AuthContext from "../stores/AuthContext";
import fakeAuth from "../utils/fakeAuth";
const AuthProvider = ({ children }) => {
  const navigate = useNavigate();
  const location = useLocation();
  const [token, setToken] = React.useState(null);
  const handleLogin = async () => {
    const token = await fakeAuth();
    setToken(token);
    const origin = location.state?.from?.pathname || "/dashboard";
    navigate(origin);
  };
  const handleLogout = () => {
    setToken(null);
  };
  const value = {
    token,
    onLogin: handleLogin,
    onLogout: handleLogout,
  };
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
export default AuthProvider;
ProtectedRoute.jsx
import * as React from "react";
import { Navigate, useLocation } from "react-router-dom";
import useAuth from "../hooks/useAuth";
const ProtectedRoute = ({ children }) => {
  const { token } = useAuth();
  const location = useLocation();
  if (!token) {
    return <Navigate to="/home" replace state={{ from: location }} />;
  }
  return children;
};
export default ProtectedRoute;
注意:react-router-dom 所依赖的版本为 "^6.0.1",完整代码

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号