如何使用React Route Config实现Protected Route(受保护路由)?
Hey there! I’ve built quite a few React apps using React Router Config, so let me walk you through exactly how to set up protected routes with this approach. It’s a clean, scalable way to handle route authorization once you get the hang of it.
First, Let’s Understand the Core Idea
Protected routes work by wrapping your regular route components in a "gatekeeper" component that checks if the user is authenticated before rendering the protected page. If they’re not logged in, we redirect them to a login page (or another public route).
Step 1: Create a ProtectedRoute Component
This is the heart of the implementation. It’ll handle the authentication check and either render the protected component or redirect the user.
First, set up an authentication state manager using React Context—it’s lightweight and built-in:
// AuthContext.js import React, { createContext, useContext, useState, useEffect } from 'react'; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // Initialize auth state on app load useEffect(() => { const token = localStorage.getItem('authToken'); if (token) { // Replace this with your actual token validation API call fetch('/api/validate-token', { headers: { Authorization: `Bearer ${token}` } }) .then(res => res.json()) .then(userData => setUser(userData)) .catch(() => setUser(null)) .finally(() => setIsLoading(false)); } else { setIsLoading(false); } }, []); // Helper methods for login/logout const login = (token, userData) => { localStorage.setItem('authToken', token); setUser(userData); }; const logout = () => { localStorage.removeItem('authToken'); setUser(null); }; return ( <AuthContext.Provider value={{ user, isLoading, login, logout }}> {children} </AuthContext.Provider> ); }; export const useAuth = () => useContext(AuthContext);
Now build the ProtectedRoute component using this context:
// ProtectedRoute.js import React from 'react'; import { Route, Redirect } from 'react-router-dom'; import { useAuth } from './AuthContext'; const ProtectedRoute = ({ protectedComponent: Component, ...rest }) => { const { user, isLoading } = useAuth(); // Show loading state while we check auth status if (isLoading) { return <div>Loading your session...</div>; // Replace with your custom loader } return ( <Route {...rest} render={(props) => // If user exists, render the protected component; else redirect to login user ? ( <Component {...props} /> ) : ( <Redirect to="/login" /> ) } /> ); }; export default ProtectedRoute;
Step 2: Set Up Your Route Config Array
Instead of defining routes directly in your JSX, create a config array that react-router-config can render. This makes your route structure easier to manage, especially for large apps.
// routes.js import Home from './components/Home'; import Login from './components/Login'; import Dashboard from './components/Dashboard'; import Settings from './components/Settings'; import ProtectedRoute from './components/ProtectedRoute'; const routes = [ { path: '/', exact: true, component: Home }, { path: '/login', component: Login }, // Protected routes use our ProtectedRoute component { path: '/dashboard', component: (props) => <ProtectedRoute {...props} protectedComponent={Dashboard} /> }, { path: '/settings', component: (props) => <ProtectedRoute {...props} protectedComponent={Settings} /> } ]; export default routes;
Step 3: Render the Routes in Your App
Finally, use renderRoutes from react-router-config to render your route config inside a Router component:
// App.js import React from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; import { renderRoutes } from 'react-router-config'; import { AuthProvider } from './AuthContext'; import routes from './routes'; function App() { return ( <AuthProvider> <Router> {renderRoutes(routes)} </Router> </AuthProvider> ); } export default App;
Bonus: Handling Role-Based Access
If you need to restrict routes to specific user roles, extend the ProtectedRoute component to check user roles:
// Updated ProtectedRoute.js const ProtectedRoute = ({ protectedComponent: Component, requiredRoles, ...rest }) => { const { user, isLoading } = useAuth(); if (isLoading) { return <div>Loading...</div>; } // Check if user has required roles (if specified) const hasRequiredRole = requiredRoles ? requiredRoles.some(role => user.roles.includes(role)) : true; if (!user) { return <Redirect to="/login" />; } if (!hasRequiredRole) { return <Redirect to="/unauthorized" />; // Create this page for access denied } return <Component {...rest} />; };
Then update your route config to include roles:
// routes.js { path: '/admin', component: (props) => <ProtectedRoute {...props} protectedComponent={AdminPanel} requiredRoles={['admin']} /> }
That’s it! This setup keeps your route authorization logic centralized and easy to maintain.
内容的提问来源于stack exchange,提问作者Rahul Sonawane

