import React, { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
import Cookies from "js-cookie";
import axios from "axios";
function PrivateRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
async function checkAuth() {
try {
axios.defaults.withCredentials = true;
const sessionId = Cookies.get("sessionId");
const data = {
sessionId: sessionId,
};
if (sessionId) {
const response = await axios.get("http://127.0.0.1:5000/session", {
params: data,
});
console.log(response.status);
if (response.status === 200) {
console.log("authenticated");
setIsAuthenticated(true);
} else {
console.log("unauthenticated");
setIsAuthenticated(false);
}
}
} catch (err) {
console.error(err);
setIsAuthenticated(false);
}
}
checkAuth();
console.log(isAuthenticated);
return isAuthenticated ? children : <Navigate to="/login" />;
}
export default PrivateRoute;
IVE试图在我的if语句中登录它,并且它有效,并且在调用CheckAuth函数后记录iSauthenticatienced时,它仍然是错误的。
其他人提到的,对状态更新进行了反应,以优化性能,这意味着
如果您不使用诸如
useSWR
之类的客户端缓存库,那么请通过React文档,正确的方法是在
useEffect()
中进行数据获取。只需确保有一个ignore
标志即可避免潜在的比赛条件,并为null
状态增加了何时仍在加载的状态(又称您决定允许用户访问或导航它们之前)。最后,您的组件应该看起来像这样:
import React, { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
import Cookies from "js-cookie";
import axios from "axios";
function PrivateRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(null);
const sessionId = Cookies.get("sessionId");
useEffect(() => {
let ignore = false;
async function checkAuth() {
try {
axios.defaults.withCredentials = true;
if (sessionId) {
const response = await axios.get("http://127.0.0.1:5000/session", { params: { sessionId } });
const isSuccess = response.status === 200;
if (!ignore) {
console.log(isSuccess ? "authenticated" : "unauthenticated");
setIsAuthenticated(isSuccess);
}
}
} catch (err) {
if (!ignore) {
console.error(err);
setIsAuthenticated(false);
}
}
}
checkAuth();
return () => { ignore = true; };
}, [sessionId]);
console.log(isAuthenticated);
if (isAuthenticated === null) return "Loading...";
return isAuthenticated ? children : <Navigate to="/login" />;
}
export default PrivateRoute;
function PrivateRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
async function checkAuth() {
// api call and set isAuthenticated
}
useEffect(() => {
checkAuth();
}, []);
// should expecte this line to run twice
// false for the first time as the component first mounted (1st render)
// ture or false for the second time when the api call is completed (2nd render)
console.log(isAuthenticated);
return isAuthenticated ? children : <Navigate to="/login" />;
}
export default PrivateRoute;
console.log(isAuthenticated);
setIsAuthenticated(true);
设置功能仅更新下一个渲染的状态变量。如果您在调用设置功能后读取状态变量,则在调用之前仍将获取屏幕上的旧值。doc