英文:
React Router Dom Private Route not Working
问题
这是您提供的代码的翻译部分:
PrivateRoute:
import { useState, useEffect } from 'react';
import { useRef } from 'react';
import { Outlet, Navigate, useLocation } from 'react-router-dom';
import Axios from "axios";
import Cookies from "universal-cookie";
export default function ProtectedRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState();
// 添加加载状态,最初为true以进行初始渲染
const [isLoading, setIsLoading] = useState(true);
const checkAuth = async () => {
const cookie = new Cookies();
setIsLoading(true); // <-- 在开始进行身份验证检查时设置为true
try {
if (cookie.get("stytch_session") == null) {
console.log("没有Cookie!")
setIsAuthenticated(false);
} else {
Axios.post(
"http://localhost:5001/test",
{},
{ headers: { sessiontoken: cookie.get("stytch_session") } }
)
.then((response) => {
console.log("到达私有路由!")
setIsAuthenticated(true);
})
.catch((err) => {
console.log(err)
setIsAuthenticated(false);
});
}
} finally {
setIsLoading(false); // <-- 当完成时清除加载状态
}
};
useEffect(() => {
checkAuth();
}, []);
if (isLoading) {
return <div className=""></div>;
}
return isAuthenticated ? children : <Navigate to="/login" />;
}
这是在app.js中调用的代码片段:
<Route
path="/scroll"
element={(
<ProtectedRoute>
<Scroll />
</ProtectedRoute>
}
/>
希望这些翻译对您有所帮助。如果您有任何其他问题,请随时提出。
英文:
I am trying to implement a private route towards my application, and while it correctly reaches the private route when authenticated, it redirects it to the login page rather than the children. I've tried every solution on stackoverflow but they don't seem to work. It's strange because it reaches the right path (I print to console whenever I reach the private route) but it's not able to redirect the page correctly.
PrivateRoute
import { useState, useEffect } from 'react';
import { useRef } from 'react';
import { Outlet, Navigate, useLocation } from 'react-router-dom';
import Axios from "axios";
import Cookies from "universal-cookie";
export default function ProtectedRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState();
// add loading state, initially true for initial render
const [isLoading, setIsLoading] = useState(true);
const checkAuth = async () => {
const cookie = new Cookies();
setIsLoading(true); // <-- set true when starting auth check
try {
if (cookie.get("stytch_session") == null) {
console.log("no cookies!")
setIsAuthenticated(false);
} else {
Axios.post(
"http://localhost:5001/test",
{},
{ headers: { sessiontoken: cookie.get("stytch_session") } }
)
.then((response) => {
console.log("reaching private route!")
setIsAuthenticated(true);
})
.catch((err) => {
console.log(err)
setIsAuthenticated(false);
});
}
} finally {
setIsLoading(false); // <-- clear loading state when completed
}
};
useEffect(() => {
checkAuth();
}, []);
if (isLoading) {
return <div className="">Loading...</div>;
}
return isAuthenticated ? children : <Navigate to={"/login"} />;
}
And here is the code snippet that's called in app.js
<Route
path="/scroll"
element={(
<ProtectedRoute>
<Scroll />
</ProtectedRoute>
}
/>
答案1
得分: 1
The axios.post
启动了一个异步 Promise 链,同步代码不会等待它。finally
块在 POST 请求解析之前执行。
代码应该 await
该 Promise 来解析。
export default function ProtectedRoute() {
const [isAuthenticated, setIsAuthenticated] = useState();
// 添加加载状态,初始值为 true,用于初始渲染
const [isLoading, setIsLoading] = useState(true);
const checkAuth = async () => {
const cookie = new Cookies();
setIsLoading(true);
try {
if (cookie.get("stytch_session") == null) {
console.log("no cookies!")
setIsAuthenticated(false);
} else {
await Axios.post(
"http://localhost:5001/test",
{},
{ headers: { sessiontoken: cookie.get("stytch_session") } }
);
console.log("reaching private route!")
setIsAuthenticated(true);
} catch(err) {
console.log(err);
setIsAuthenticated(false);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
checkAuth();
}, []);
if (isLoading) {
return <div className="">Loading...</div>;
}
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
}
<Route element={<ProtectedRoute />}>
<Route path="/scroll" element={<Scroll />} />
...其他受保护的路由...
</Route>
英文:
The axios.post
starts an asynchronous Promise chain that the synchronous code around it doesn't wait for. The finally
block is executed prior to the POST request resolving.
The code should await
the Promise to resolve.
export default function ProtectedRoute() {
const [isAuthenticated, setIsAuthenticated] = useState();
// add loading state, initially true for initial render
const [isLoading, setIsLoading] = useState(true);
const checkAuth = async () => {
const cookie = new Cookies();
setIsLoading(true);
try {
if (cookie.get("stytch_session") == null) {
console.log("no cookies!")
setIsAuthenticated(false);
} else {
await Axios.post(
"http://localhost:5001/test",
{},
{ headers: { sessiontoken: cookie.get("stytch_session") } }
);
console.log("reaching private route!")
setIsAuthenticated(true);
} catch(err) {
console.log(err);
setIsAuthenticated(false);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
checkAuth();
}, []);
if (isLoading) {
return <div className="">Loading...</div>;
}
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
}
<Route element={<ProtectedRoute />}>
<Route path="/scroll" element={<Scroll />} />
... other protected routes ...
</Route>
答案2
得分: 0
你可以尝试在你的私有路由是 ProtectedRoute
组件的子组件时使用 Outlet
,就像下面这样。
return isAuthenticated ? <Outlet /> : <Navigate to={"/login"} />;
英文:
Could you try using Outlet if your private route is child of ProtectedRoute
component? Like following.
return isAuthenticated ? <Outlet />: <Navigate to={"/login"} />;
答案3
得分: 0
尝试移除finally
并替换为
useEffect(() => {
if (isAuthenticated !== null) {
setIsLoading(false);
}
}, [isAuthenticated])
在我看来,你的状态更新可能正在批处理或以错误的顺序解析。这将确保 isLoading
保持为 true
,直到 isAuthenticated
具有实际值。
英文:
Try removing the finally and putting in
useEffect(()=>{
if(isAuthenticated !== null){
setIsLoading(false);
}
},[isAuthenticated])
What it looks like to me is that your state updates are being batched or resolving in the wrong order. This will ensure that isLoading remains true until isAuthenticated has a real value.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论