英文:
How to avoid redirect from logged in page to home(login page) by changing the url manually-react
问题
以下是您要翻译的代码部分:
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;
关于在本地存储中持久保存身份验证状态的问题,您尝试使用localStorage
是一个合理的方法。但是,由于您正在使用Redux Toolkit,您也可以将身份验证状态存储在Redux store 中,以便更好地与您的应用程序状态管理一起使用。这将取决于您的应用程序的需求和偏好。
英文:
Say the user is already logged in and redirected to home page again if he modifies the url to navigate to login page it should not do go back to login.
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
I tried persisting the state Auth with local storage, since data wont be available it shows undefined
/null
.
const isAuthenticated = localStorage.getItem('data');
if (isAuthenticated) {
setAuthenticationStatus(true);
since I am using Redux Toolkit I am not sure if I have to use localStorage
to persist the data.
Any solution would be appreciated
first render localhost:3000(loginPage)
After successfull LoggedIn localhost:3000/home
Manually i change the URL: localhost:3000/ it comes back to login page
答案1
得分: 1
以下是您要的翻译内容:
主要问题是isAuthenticated
状态未持久化到长期存储,并且在应用挂载时也未从长期存储中初始化。
更简单的短期解决方案是使用在App
中声明的isAuthenticated
状态,并将isAuthenticated
状态和更新函数作为属性传递给需要它的路由组件。
为了解决“已认证”用户后续访问"/login"
路由的问题,答案是创建另一个路由保护组件,它应用了ProtectedRoutes
组件的反向,例如,已认证的用户将被从路由中移除。
路由保护器:
import React from "react";
import { Navigate, Outlet } from "react-router-dom";
// 未认证用户重定向到登录路由
const ProtectedRoute = ({ isAuthenticated }) => {
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
};
// 已认证用户重定向到安全路由
const AnonymousRoute = ({ isAuthenticated }) => {
return isAuthenticated ? <Navigate to="/" replace /> : <Outlet />;
};
function App() {
// 从本地存储初始化状态
const [isAuthenticated, setIsAuthenticated] = useState(() => {
return JSON.parse(localStorage.getItem("auth")) ?? false;
});
// 副作用,将状态更改持久化到本地存储
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} />} />
{/* ... 其他“匿名”路由 ... */}
</Route>
<Route element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
<Route path="/home" element={<Home />} />
{/* ... 其他“已认证”路由 ... */}
</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 {
// 调用突变触发器并等待和解包已解决的响应
await loginUser({ email, password }).unwrap();
// 更新认证状态
onLogin();
// 重定向回主页
navigate("/home", { replace: true });
} catch(error) {
setErrorMsg(true);
}
};
...
};
英文:
The main issue is that the isAuthenticated
state isn't persisted to any longterm storage and ins't initialized from longterm storage when the app mounts.
The easier short-term solution is to use the isAuthenticated
state that's declared in App
and pass isAuthenticated
state and updater function down as props to the routed components that need it.
To combat the issue of "authenticated" users later accessing the "/login"
route the answer is to create another route protection component that applies the inverse of the ProtectedRoutes
component, e.g. authenticated users are bounced off the route.
Route protectors:
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);
}
};
...
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论