首页 > 解决方案 > 如果在我的回调函数完成之前执行语句,这使得 react-router-dom 无法重定向

问题描述

现在我正在尝试在我的爱好项目中实现身份验证。您可以在我的GitHub 存储库中找到代码。我从这个Code Sandbox获得了身份验证的灵感。

几天来,我一直在尝试通过回调在我的应用程序中使用此身份验证并尝试异步操作。我将继续这样做。但是,我准备寻求一点帮助。

protected.route.js

import React from "react";
import { Route, Redirect } from "react-router-dom";
import auth from "./auth";
import {history} from './history'

export function ProtectedRoute({component: Component, ...rest})  {
  return (
    <Route
      {...rest}
      render={props => {
        if (auth.checkAuthentication()) {
          console.log("hmmmmmmmmm true")
          return <Component {...props} />;
        } else {
          console.log("hmmmmmmmmm false")
          return (
            <Redirect
              to={{
                pathname: "/SignIn",
                state: {
                  from: props.location
                }
              }}
            />
          );
        }
      }}
    />
  );
};

auth.js

...some code...

    async checkAuthentication(){
        const token = window.localStorage.getItem(AuthTokenKey)

        console.log("checking auth")
        console.log(token)

        await axios.get('http://127.0.0.1:8000/api/user/me/', {
            headers: {
                'Access-Control-Allow-Origin': '*',
                'Content-Type': 'application/json',
                'Access-Control-Allow-Credentials': 'true',
                'Authorization': 'Token ' + token
            },
        })
        .then((response) => {
            if(response.status===200){
                console.log('auth check passed')
                return true
            } else {
                return false
            }
        }, (error) => {
            console.log(error);
            return false
        })
    }

...some code...

我希望该if语句protected.route.js等到 axios GET 请求完成。但是,它只是不断返回 true 并且从不重定向。

标签: reactjsauthenticationasynchronousaxiosreact-router-v4

解决方案


if (auth.checkAuthentication()) {

由于 checkAuthentication 是一个异步函数,它返回一个 promise 对象。对象是“真实的”,所以这个条件通过了。

要获得 promise 的结果,你需要使用它的 .then 方法,或者使用 async/await,但是还有另一个更大的问题:你不能在 react render 方法(或 route render prop)中做异步的事情。您将需要一些组件状态,一些根据该状态决定要呈现什么的代码,以及一些检查身份验证和更新状态的代码。

例如:

export function ProtectedRoute({component: Component, ...rest})  {
  const [authentication, setAuthentication] = useState('pending');

  useEffect(() => {
    auth.checkAuthentication().then(result => setAuthentication(result));
  }, []);

  if (authentication === 'pending') {
    return null; // or some placeholder
  } else if (authentication === false) {
    return <Redirect /* props omitted for brevity */ /> 
  } else {
    return <Route {...rest} render={props => <Component {...props} />} />
  }
};

您还需要修复您的 checkAuthentication 函数,因为目前它没有返回语句,因此将解析为未定义。Matt Oestreich 的建议(来自现已删除的答案)将起到作用:

async checkAuthentication(){
  const token = window.localStorage.getItem(AuthTokenKey);

  console.log("checking auth");
  console.log(token);

  try {
    let response = await axios.get('http://127.0.0.1:8000/api/user/me/', {
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Credentials': 'true',
        'Authorization': 'Token ' + token
      },
    });

    if (response.status === 200) {
      console.log('auth check passed');
      return true;
    }

    return false;
  } catch (error) {
    console.log(error);
    return false;
  }
}

推荐阅读