[Snippet] - Authentication in React Router
create:January 19, 2022 update:April 12, 2022 • ☕️ 4 min read
同步链接: https://www.shanejix.com/posts/[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”,完整代码
作者:shanejix 出处:https://www.shanejix.com/posts/[Snippet] - Authentication in React Router/ 版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。 声明:转载请注明出处!