如何正确等待此axios.get请求?

时间:2019-12-20 17:30:40

标签: javascript reactjs asynchronous axios react-router-dom

很抱歉,如果我忽略了这件事非常简单,但是我试图制造一个组件,该组件基本上只将某些React-Router路由限制为仅具有有效令牌的用户。

import Axios from "axios";
import React, {useState, useEffect, useSelector} from 'react';
import {Route, Redirect} from 'react-router-dom';

function isLogin(){
    const result = Axios.get('http://localhost:8081/authentication', {withCredentials: true})
    .then(res => {
        console.log(res);
    })
    console.log(result);
}

const PrivateRoute = ({component: Component, ...rest}) => {

    return (
        <Route {...rest} render={props => (
            isLogin() ?
                <Component {...props} />
            : <Redirect to="/login" />
        )} />
    );
};

export default PrivateRoute;

似乎(仅预期)仅使用未完成的promise执行“ console.log(result)”,但最终结果是,我尝试将一些逻辑编码到后端给出的响应中(true或false),然后应将其向下发送到PrivateRoute组件,以确定是否应将用户发送回登录名等。

我知道这一定是因为axios.get的异步特性导致了我的问题,但是我尝试了几种不同的方法:

使isLogin函数异步,然后等待axios请求

在PrivateRoute返回中的另一个异步创建函数,等待。

似乎我在这里尝试执行的操作都没有正确等待axios.get的结果,从而导致产生不必要的结果。 希望您能提供任何建议,甚至是正确的方向。

谢谢。

2 个答案:

答案 0 :(得分:0)

正如@Emile Bergeron在评论(引用)中所说,我将向私有Route组件添加一个状态,如果用户通过了身份验证,该状态将存储。首次安装组件(专用路由)时,将对此进行检查。

作为代码,以您的代码为基础看起来像这样:

import Axios from "axios";
import React, {useState, useEffect, useSelector} from 'react';
import {Route, Redirect} from 'react-router-dom';

const PrivateRoute = ({component: Component, ...rest}) => {
    // State
    const [authenticated, setAuthentication] = useState(null);
    const [loadingComplete, setLoadingComplete] = useState(false);
    // Login function
    useEffect(
        () => {
            // ComponentDidMount
            // Declare Function (you can also declare it outside the useEffect, 
            //    if you want to run it also if another prop changes for instance.
            //    But it will be overwritten on every rerender; 
            //    To prevent this you could use useCallback hook)
            const isLogin = async () => {
                try {
                    const result = await Axios.get('http://localhost:8081/authentication', {withCredentials: true});
                    // Store the result, e.g. ID, token, ...
                    setAuthentication(result);
                } catch (e) {
                    // Something failed
                    console.log(e);
                }
                setLoadingComplete(true);
            }   
            // run login function
            isLogin();
        },
        []
    );
    if(loadingComplete){
        return (
            <Route {...rest} render={props => (
                !!authenticated ?
                    <Component {...props} />
                : <Redirect to="/login" />
            )} />
        );
    }else{
        return ( <div> Loading... </div>);
    }
};

export default PrivateRoute;

编辑:当然,您还需要一个加载过程状态,因此重定向不会在您获取用户之前命中您。

答案 1 :(得分:0)

我已经制作了gist来处理这种情况。

您需要2个状态。

  • 已验证
  • 正在加载

您将具有一个对用户进行身份验证的功能,但在身份验证时还需要一个加载状态。

所以您会得到

return (
    <Route
        {...rest}
        render={props => (
            !isLoading
                ?
                (
                    isAuthenticated
                        ?
                        <Component {...props} />
                        :
                        <Redirect to="/login" />
                )
                :
                <Loading />
        )}
    />
)

您将拥有一个可以设置这些状态的函数

useEffect(() => {
    setIsLoading(true)
    isLogin()
        .then(() => {
            setIsAuthenticated(true)
        })
        .catch(() => {
            setIsAuthenticated(false)
        })
        .then(() => {
            setIsLoading(false)
        })
}, [])