如何等待reactJS中useState的状态更改来检查用户是否在仪表板上经过身份验证?使用上下文 API

问题描述 投票:0回答:1

所以我正在使用 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 更新之前读取用户状态的旧值,即“用户”状态的值。

有什么办法可以解决这个问题吗?还是我做错了什么?

javascript reactjs react-hooks
1个回答
2
投票

您可以将

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;
© www.soinside.com 2019 - 2024. All rights reserved.