首页 > 解决方案 > REACT - useContext 状态共享同步问题

问题描述

客观的 : -

我希望用户只有在登录时才能看到他/她的订单。所以我使用 AuthContext 对登录数据+令牌的用户进行状态管理。

问题 : -

当我将令牌从 AuthContext 传递给子组件时,AuthContext 需要一些时间来使用后端验证令牌,同时子组件的逻辑会中断。

子组件(使用状态/令牌):

const MyOrders = () => {
    const { userData } = useContext(AuthContext);
    const history = useHistory();
    if (!userData.token) {      // This redirects the user back to the home page immediately
        history.push("/");      // because the token hasn't been passed yet when
                                // the component is loaded
    };
    const getOrders = async () => {
        const url = 'http://localhost:5000/api/orders';
        try {
            const res = await axios.get(url, {
                headers: {
                    'x-auth-token': userData.token
                }
            });
            console.log(res.data);
        } catch (err) {
            console.log(err.response);
        }
    };
    useEffect(() => {
        if (userData.token) getOrders();
    }, []);

解决方法(安全吗????)

const MyOrders = () => {
    const token = localStorage.getItem('auth-token');  // Use localStorage token directly instead of 
                                                    // validating the token first (from AuthContext)??
    const history = useHistory();
    if (!token) {      
        history.push("/");                                      
    };

    const getOrders = async () => {
        const url = 'http://localhost:5000/api/orders';
        try {
            const res = await axios.get(url, {
                headers: {
                    'x-auth-token': token
                }
            });
            console.log(res.data);
        } catch (err) {
            console.log(err.response);
        }
    };

    useEffect(() => {
        if (userData.token) getOrders();
    }, []);

Parent Component (AuthContext) : // 如果有人需要

const AuthContextProvider = (props) => {
    const [userData, setUserData] = useState({
        token: undefined,
        user: undefined
    });
    //Need to check if user is logged in
    //every time the App is rendered
    useEffect(() => {
        const checkLoggedIn = async () => {
            const url = "http://localhost:5000/api/users/token";
            let token = localStorage.getItem("auth-token");
            //when user is not logged in
            if(token === null) {
                localStorage.setItem("auth-token", "");
                token = "";
            }
            //need to validate the token if it exists
            const tokenResponse = await axios.post(url, null, {
                headers: { "x-auth-token": token }
            });
            //if token is valid, collect user data 
            if(tokenResponse.data){
                console.log(tokenResponse);
                setUserData({
                    token,
                    user: tokenResponse.data,

                });
            } else {
                localStorage.setItem("auth-token", "");
                token = "";
            };
        };
        checkLoggedIn();                
    }, []);

标签: reactjsreact-nativereact-reduxreact-router

解决方案


我建议您尝试在应用程序的第一页中检索保存的令牌。在函数上使用“等待”。尝试从 localStorage 检索完成后,如果令牌不存在,您应该导航到登录,否则导航到主页。在这种情况下,如果您有令牌,您将不会有未定义的令牌,

但是如果令牌以某种方式未定义怎么办?如果用户尝试使用未定义的令牌获取,则需要从服务器发送未经授权的错误,然后在客户端捕获错误,检查您收到的消息和类型,如果出现授权错误,导航到主页页。

这是一个有点复杂的答案,但它肯定会解决你的问题,它会让它更干净的代码和可靠的。


推荐阅读