const PrivateRoute = ({ children }) => {
const [user, setUser] = useLocalState("", "user");
const [isAuthorized, setIsAuthorized] = useState(false);
const [privilege, setPrivilege] = useState(null);
const [shouldRender, setShouldRender] = useState(false);
useEffect(() => {
async function checkPriv() {
if (user.hasOwnProperty("email")) {
const response = await fetch("http://localhost:3001/check-authorization", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email: user.email }),
});
const data = await response.json();
console.log("data: ", data, "is authorized: ", data.isAuthorized, "is priv: ", data.privilege);
setIsAuthorized(data.isAuthorized);
setPrivilege(data.privilege);
console.log("got data back");
console.log(privilege);
if (data.isAuthorized && data.privilege === "manager") {
console.log("user found");
setShouldRender(true);
} else {
console.log("priv failed");
setShouldRender(false);
}
}
}
checkPriv();
}, []);
useEffect(() => {
console.log("isAuthorized: ", isAuthorized);
console.log("privilege: ", privilege);
if (isAuthorized && privilege === "manager") {
console.log("user found");
setShouldRender(true);
} else {
console.log("priv failed");
setShouldRender(false);
}
}, []);
const renderedComponent = useMemo(()=>{
console.log("rednsdsdk")
if (shouldRender) {
return children;
} else {
return <Navigate to="/" />;
}
},[]);
return renderedComponent;
};
export default PrivateRoute;
我不明白为什么我不能在这里使用更新后的 shouldRender 值。我知道除非在 useEffect 中,否则 useStates 不会更新,但是在 useEffect 之外更新是否会被覆盖?如果这是一个愚蠢的问题,我很抱歉,仍然是新手。
我也试过在没有任何状态的情况下使用它,但它仍然没有用
好吧,让我帮你做很多清理和重写工作
const PrivateRoute = React.memo(({ children }) => {
const [user, setUser] = useLocalState("", "user");
const [isAuthorized, setIsAuthorized] = useState(false);
const [privilege, setPrivilege] = useState(null);
const [shouldRender, setShouldRender] = useState(false);
const make_request = React.useCallback(async () => {
return await fetch("http://localhost:3001/check-authorization", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email: user.email }),
})
.then(res => res.json())
.then(data => data);
}, [user])
const checkPriv = React.useCallback(async () => {
if (user.hasOwnProperty("email")) {
const data = await make_request()
console.log("data: ", data, "is authorized: ", data.isAuthorized, "is priv: ", data.privilege);
setIsAuthorized(data.isAuthorized);
setPrivilege(data.privilege);
console.log("got data back");
console.log(privilege);
if (data.isAuthorized && data.privilege === "manager") {
console.log("user found");
// do something here if success
setShouldRender(true);
} else {
console.log("priv failed");
// do something here if it failed
setShouldRender(false);
// since you want to navigate to "/" if the check is false, you can simply do it here
document.location.assign('/')
}
}
}, [user])
useEffect(() => {
checkPriv();
}, []);
return shouldRender ? children : '';
});
export default PrivateRoute;
使用 shouldRender 在显示内容之前检查用户是否被授权,
useCallback
是一个 React hook,用于在 React 中创建 memoised 回调函数,因此为了防止重新渲染问题,您可以在线了解更多关于 React hooks 的信息,我将请求放在函数之外以实现可重用性,并且我还记住了组件而不是您在代码中使用的 useMemo 函数,这些是 React JS 中创建具有最佳用户体验的 React 应用程序的最佳实践
你说 useState 除了在 useEffect 中不会更新,不,它可以在组件内的任何地方更新,要在函数或挂钩中使用状态,必须将状态变量作为依赖项传递给挂钩,否则它当你使用函数或钩子内部的状态时不会更新,以供解释
exampleState
是您想在函数内部使用的状态,使用它的最佳方法是将函数包装在 useCallback 挂钩中,并将状态作为依赖项传递给它,如下所示:
const exampleFn = React.useCallback(() => {
// then when you call this function exampleState's value will be an updated value
}, [exampleState])
如果有帮助请告诉我