React 路由器 v6,在登录时刷新页面时,留在该页面上,不要返回"/dashboard"



我使用React router v6和Outlet组件来渲染子组件。

当我在url路径"/predict-scores"上时,只有在登录时才能到达,如果用户刷新页面,我想留在页面上,而不是回到"/dashboard"。什么好主意吗?

App.tsx:

import React, { Suspense } from "react";
import { Provider } from "react-redux";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import "./App.css";
import { PrivateRoutes } from "./components/privateRoutes/PrivateRoutes";
import TopNavBar from "./components/topNavBar/TopNavBar";
import Dashboard from "./pages/dashboard/Dashboard";
import Login from "./pages/login/Login";
import Predict from "./pages/predict/predict";
import Register from "./pages/register/Register";
import Reset from "./pages/reset/Reset";
import Results from "./pages/results/Results";
import { store } from "./store";
function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<TopNavBar />
<div className="px-4 mt-4 grid place-items-center">
<Routes>
<Route path="/" element={<PrivateRoutes />}>
<Route path="/" element={<Navigate to="/dashboard" />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/results" element={<Results />} />
<Route path="/predict-scores" element={<Predict />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/reset" element={<Reset />} />
</Routes>
</div>
</Suspense>
</BrowserRouter>
</Provider>
);
}
export default App;

PrivateRoutes.tsx:

import { useAuthState } from "react-firebase-hooks/auth";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { auth } from "../../services/firebase/firebase-auth";
export const PrivateRoutes = () => {
const location = useLocation();
const [user] = useAuthState(auth);
return user ? <Outlet /> : <Navigate to="/login" replace state={{ from: location }} />;
};

我必须将用户保存在localStorage中,然后我引用它来控制路由器。我必须使用redux用户对象来识别firestore何时注销,因为react组件无法检测localStorage更改,只能检测redux更改。useEffect只会在检测到更改后重新渲染某些内容,因此我使用redux用户作为依赖项数组中的引用。

PrivateRoutes.tsx:

import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { RootState } from "../../store";
export const PrivateRoutes = () => {
const location = useLocation();
const [userInLocalStorage, setUserInLocalStorage] = useState([]);
const userDetails: any = useSelector((state: RootState) => state.userDetails);
useEffect(() => {
const userObject = JSON.parse(localStorage.getItem("scorePredictor") as any);
setUserInLocalStorage(userObject);
}, [userDetails]);
return userInLocalStorage ? <Outlet /> : <Navigate to="/login" replace state={{ from: location }} />;
};

设置和删除LocalStorage:

const logInWithEmailAndPassword = async (email: any, password: any) => {
try {
const res = await signInWithEmailAndPassword(auth, email, password);
const user = res.user;
localStorage.setItem("scorePredictor", JSON.stringify(user));
return res;
} catch (err: any) {
console.error(logInWithEmailAndPassword, err);
alert("logInWithEmailAndPassword" + err.message);
}
}
const logout = () => {
localStorage.removeItem("scorePredictor");
return signOut(auth);
};