如何通过手动更改url来避免从登录页面重定向到主页(登录页面)



假设用户已经登录并再次重定向到主页,如果他修改url以导航到登录页面,则不应该返回登录。

Login.js

const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
useEffect(() => {
if (data?.response === "true" && data?.state === "success"){
setErrorMsg("");
setEmail("");
setPassword("");
setIsAuthenticated(true);
navigate("/home", { state: { user: data?.user } });
}
else if (data?.response === "false" && data.state === "error"){
setErrorMsg(true);
}
else{
setErrorMsg(false)
}
}, [data,isError,isLoading]);
const handleLogin = async (e) => {
e.preventDefault();
console.log("****")
await loginUser({email,password})
}

App.js

function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const handleLogin = () => {
setIsAuthenticated(true);
}
return (
<div className="App">
<Router>
<Routes>
<Route exact path="/">
<Login onLogin={handleLogin} />
</Route>
<ProtectedRoute path="/home" component={Home} isAuthenticated= 
{isAuthenticated}/>
</Routes>
</Router>
</div>
);
}
export default App;

protectedRoute.js

import React from "react";
import { Navigate,Outlet } from "react-router-dom";
const ProtectedRoute = ( {isAuthenticated}) => {
return isAuthenticated? <Outlet /> : <Navigate to="/" />;
}
export default ProtectedRoute;

UserApi

import{createApi,fetchBaseQuery} from'@reduxjs/toolkit/query/react'
export const authApi = createApi({
reducerPath: 'authApi',
baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:8100" }),
endpoints: (builder) => ({
loginUser: builder.mutation({
query: (body) => {
return {
url: "users/authenticate",
method: "post",
body,
};
},
transformResponse: (response) => {
const { response: resp, state, user } = response;
return { response: resp, state: state, user: user };
},
}),
}),
});
export const { useLoginUserMutation } = authApi;
enter code here

我尝试用本地存储持久化状态认证,因为数据不可用,它显示undefined/null

const isAuthenticated = localStorage.getItem('data');
if (isAuthenticated) {
setAuthenticationStatus(true);

由于我使用Redux Toolkit,我不确定是否必须使用localStorage来持久化数据。

任何解决方案都将不胜感激

第一个渲染localhost:3000(loginPage)LoggedIn localhost:3000/home我手动更改URL: localhost:3000/它返回到登录页

主要问题是isAuthenticated状态没有持久到任何长期存储,并且在应用程序挂载时没有从长期存储初始化。

更简单的短期解决方案是使用在App中声明的isAuthenticated状态,并将isAuthenticated状态和updater函数作为道具传递给需要它的路由组件。

解决"authenticated"用户稍后访问"/login"路由的答案是创建另一个路由保护组件,应用反向的ProtectedRoutes组件,例如,通过认证的用户从路由上被反弹。

路线保护者:

import React from "react";
import { Navigate, Outlet } from "react-router-dom";
// Unauthenticated users redirected to log in route
const ProtectedRoute = ({ isAuthenticated }) => {
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
};
// Authenticated users redirected to safe route
const AnonymousRoute = ({ isAuthenticated }) => {
return isAuthenticated ? <Navigate to="/" replace /> : <Outlet />;
};
function App() {
// Initialize state from localStorage
const [isAuthenticated, setIsAuthenticated] = useState(() => {
return JSON.parse(localStorage.getItem("auth")) ?? false;
});
// Side-effect to persist state changes to localStorage
useEffect(() => {
localStorage.setItem("auth", JSON.stringify(isAuthenticated));
}, [isAuthenticated]);
const handleLogin = () => {
setIsAuthenticated(true);
};
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/home" replace />} />
<Route element={<AnonymousRoute isAuthenticated={isAuthenticated} />}>
<Route path="/login" element={<Login onLogin={handleLogin} />} />
{/* ... other "anonymous" routes ... */}
</Route>
<Route element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
<Route path="/home" element={<Home />} />
{/* ... other "authenticated" routes ... */}
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
const Login = ({ onLogin }) => {
const navigate = useNavigate();
const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
...
const handleLogin = async (e) => {
e.preventDefault();
setErrorMsg("");
try {
// Call mutation trigger and await and unwrap resolved response
await loginUser({ email, password }).unwrap();
// Update the auth state
onLogin();
// Redirect back to home
navigate("/home", { replace: true });
} catch(error) {
setErrorMsg(true);
}
};
...
};