所以我正在使用 useContext API 对用户进行身份验证。 这是我的 AuthContext 代码,它返回带有值的 AuthContext.Provider 。
import { createContext, useEffect, useState } from "react";
const AuthContext = createContext();
export const AuthProvider = ({children}) =>{
const [user, setUser] = useState();
const [role, setRole] = useState();
const [authenticated, setAuthenticated] = useState(false);
useEffect(()=>{
const getUserData = async()=>{
const response = await fetch("http://localhost:5000/api/isAuth", {
method: "GET",
headers: {
"Content-Type":"application/json",
"x-access-token": localStorage.getItem("token"),
}
});
const json = await response.json();
if (json.userData != null) {
setUser(json.userData);
setRole(json.role);
setAuthenticated(true);
}
}
getUserData();
}, []);
return (
<AuthContext.Provider value={{
user,
setUser,
role,
setRole,
authenticated,
setAuthenticated
}}>
{children}
</AuthContext.Provider>
);
}
export default AuthContext;
现在我正在使用 AuthProvider 包装我的整个应用程序
root.render(
<React.StrictMode>
<AuthProvider>
<App />
<AuthProvider>
</React.StrictMode>
);
在仪表板页面上,我正在检查“已验证”状态的用户身份验证。 如果通过身份验证,用户将看到仪表板,否则,他将重定向到登录页面。
这是我的仪表板组件。
const {user, setUser, role, setRole, authenticated, setAuthenticated} = useContext(AuthContext);
const navigate = useNavigate();
useEffect(()=>{
if (authenticated == false) {
console.log(authenticated);
return navigate("/login");
}
}, [authenticated])
return (
<div>
{
// console.log(user.name)
}
</div>
)
现在我的问题是,在仪表板页面上,在 AuthProvider 更新“已验证”和“用户”状态的值之前,它会立即检查“已验证”值并导航到登录页面。现实生活中不应该出现这种情况。它至少应该等待状态的改变。
我尝试使用useEffect,但没有任何反应。 我还尝试将经过身份验证的状态的默认值设置为 null,并且当 fetch API 给出响应时,根据结果将值设置为 true 或 false。 但这没有什么区别。
仪表板页面上还显示“用户”为空,因为它只是在 AuthProvider 更新之前读取用户状态的旧值,即“用户”状态的值。
有什么办法可以解决这个问题吗?还是我做错了什么?
您可以将
isLoading
状态添加到您的上下文中。这将帮助您区分状态。
在
AuthContext
:
import { createContext, useEffect, useState } from "react";
const AuthContext = createContext();
export const AuthProvider = ({children}) =>{
const [user, setUser] = useState();
const [role, setRole] = useState();
const [isLoading, setIsLoading] = useState(true); //default to true
const [authenticated, setAuthenticated] = useState(false);
useEffect(()=>{
const getUserData = async()=>{
const response = await fetch("http://localhost:5000/api/isAuth", {
method: "GET",
headers: {
"Content-Type":"application/json",
"x-access-token": localStorage.getItem("token"),
}
});
const json = await response.json();
if (json.userData != null) {
setIsLoading(false) // set to false after data is fetched
setUser(json.userData);
setRole(json.role);
setAuthenticated(true);
}
}
getUserData();
}, []);
return (
<AuthContext.Provider value={{
user,
setUser,
role,
isLoading,
setRole,
authenticated,
setAuthenticated
}}>
{children}
</AuthContext.Provider>
);
}
export default AuthContext;
然后在
Dashboard
组件中:
function Dashboard(props) {
const {
user,
setUser,
isLoading,
role,
setRole,
authenticated,
setAuthenticated,
} = useContext(AuthContext);
const navigate = useNavigate();
useEffect(() => {
if (!isLoading) {
if (!authenticated) {
return navigate('/login');
}
}
}, [authenticated, isLoading]);
return <div>{isLoading ? <>Loading...</> : <>Welcome {user.name}!</>}</div>;
}
export default Dashboard;