我在 React 应用程序中遇到一个问题,登录后,刷新受保护的路由会将我重定向到根路径(“/”),但是当我刷新像 /myaccount 这样的非受保护的路由时,它不会重定向。
问题描述 登录后,如果我导航到 /dashboard 等受保护的路由并刷新页面,我将被重定向到“/”。 但是,当我位于 /myaccount 等不受保护的路由时,刷新页面不会重定向我。
期望的行为 我希望应用程序在刷新后保持当前状态,防止受保护和不受保护的路由重定向到根路径(“/”)。
我尝试过的 检查上下文中的令牌和 userType 状态管理。 确保 fetchData 函数在登录后正确检索用户类型。
代码 这是我的应用程序的相关代码: 应用程序.js
import React, { Suspense, lazy } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Layout from "./components/layout/Layout";
import { CombinedProvider } from "./contexts/useContext";
import { ToastContainer } from "react-toastify";
import ProtectedRoute from "./utils/ProtectedRoute";
const SelectionPage = lazy(() => import("./pages/SelectionPage"));
const SignupPage = lazy(() => import("./pages/Signup"));
const LoginTanod = lazy(() => import("./pages/LoginTanod"));
const LoginResident = lazy(() => import("./pages/ResidentLogin"));
// Tanod routes
const Dashboard = lazy(() => import("./components/users/tanods/Dashboard"));
const Patrolmap = lazy(() => import("./components/users/tanods/Map"));
const Equipments = lazy(() => import("./components/users/tanods/Equipment"));
const Performance = lazy(() => import("./components/users/tanods/Performance"));
const Schedule = lazy(() => import("./components/users/tanods/Schedule"));
const Incidents = lazy(() => import("./components/users/tanods/Incidents"));
const MyAccount = lazy(() => import("./components/users/tanods/MyAcc"));
// Resident routes
const ResidentRating = lazy(() => import("./components/users/residents/TanodPersonels"));
const ResidentDashboard = lazy(() => import("./components/users/residents/Dashboard"));
function App() {
return (
<div className="flex-1 p-6 bg-background text-text">
<BrowserRouter>
<CombinedProvider>
<Suspense fallback={<div>Loading...</div>}>
<ToastContainer />
<Routes>
{/* Public Routes */}
<Route path="/" element={<SelectionPage />} />
<Route path="/tanod-login" element={<LoginTanod />} />
<Route path="/resident-login" element={<LoginResident />} />
<Route path="/signup" element={<SignupPage />} />
<Route element={<Layout />}>
<Route path="/myaccount" element={<MyAccount />}/>
</Route>
{/* Protected Routes for Tanod */}
<Route element={<Layout />}>
<Route
path="/dashboard"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Dashboard /></ProtectedRoute>}
/>
<Route
path="/patrolmap"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Patrolmap /></ProtectedRoute>}
/>
<Route
path="/equipments"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Equipments /></ProtectedRoute>}
/>
<Route
path="/performance"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Performance /></ProtectedRoute>}
/>
<Route
path="/schedule"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Schedule /></ProtectedRoute>}
/>
<Route
path="/incidents"
element={<ProtectedRoute userTypeAllowed={["tanod"]}><Incidents /></ProtectedRoute>}
/>
</Route>
{/* Protected Routes for Residents */}
<Route element={<Layout />}>
<Route
path="/resident-dashboard"
element={<ProtectedRoute userTypeAllowed={["resident"]}><ResidentDashboard /></ProtectedRoute>}
/>
<Route
path="/ratetanod"
element={<ProtectedRoute userTypeAllowed={["resident"]}><ResidentRating /></ProtectedRoute>}
/>
</Route>
</Routes>
</Suspense>
</CombinedProvider>
</BrowserRouter>
</div>
);
}
export default App;
ProtectedRoute.js
import React from "react";
import { Navigate } from "react-router-dom";
import { useCombinedContext } from "../contexts/useContext";
export default function ProtectedRoute({ userTypeAllowed, children }) {
const { userType, token } = useCombinedContext();
if (!token || !userTypeAllowed.includes(userType)) {
return <Navigate to="/" />;
}
return children;
}
useContext.js
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
export const CombinedContext = createContext();
export const CombinedProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token'));
const [userType, setUserType] = useState(null);
const navigate = useNavigate();
const fetchData = useCallback(async () => {
// Fetch user data to get userType
}, []);
useEffect(() => {
if (token) {
fetchData();
}
}, [token, fetchData]);
const logout = () => {
localStorage.removeItem('token');
setToken(null);
setUserType(null);
navigate('/');
};
return (
<CombinedContext.Provider value={{ token, userType, logout }}>
{children}
</CombinedContext.Provider>
);
};
export const useCombinedContext = () => useContext(CombinedContext);
听起来您正在处理 React 应用程序中的状态持久性问题。以下是一些建议,可帮助您在刷新后保持当前状态,防止受保护和不受保护的路由重定向到根路径(“/”):
1。在本地存储中保留用户状态 确保您的用户状态(令牌和用户类型)正确保留在本地存储中并在应用程序加载时重新水合。
在 useContext.js 中,您已经将令牌存储在本地存储中。确保您还存储了 userType。
2。检查路线更改的用户状态 确保您的 ProtectedRoute 组件在渲染受保护的组件之前正确检查用户状态。
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
export const CombinedContext = createContext();
export const CombinedProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token'));
const [userType, setUserType] = useState(localStorage.getItem('userType'));
const navigate = useNavigate();
const fetchData = useCallback(async () => {
// Fetch user data to get userType
}, []);
useEffect(() => {
if (token) {
fetchData();
localStorage.setItem('userType', userType);
}
}, [token, userType, fetchData]);
useEffect(() => {
const storedToken = localStorage.getItem('token');
const storedUserType = localStorage.getItem('userType');
if (storedToken) {
setToken(storedToken);
}
if (storedUserType) {
setUserType(storedUserType);
}
}, []);
const logout = () => {
localStorage.removeItem('token');
localStorage.removeItem('userType');
setToken(null);
setUserType(null);
navigate('/');
};
return (
<CombinedContext.Provider value={{ token, userType, logout }}>
{children}
</CombinedContext.Provider>
);
};
export const useCombinedContext = () => useContext(CombinedContext);