首页 > 解决方案 > 无法理解反应中的 axios 错误处理

问题描述

我正在学习 react 和 django。我已经安装了django-rest-auth来处理用户的帐户创建和身份验证。我也想了解反应,我已经安装了 axios来向我的 django rest api 发出 http 请求。我希望有一个“启动”页面,用户将首先访问该站点。如果用户已经登录,他们将看到他们的个人资料和其他内容。如果用户没有登录,他们应该看到一个登录页面。

这是我到目前为止的 App.js 代码。

import React, { useState, useEffect } from 'react';
import axios from 'axios';

import logo from './logo.svg';
import './App.css';

function LoginPage(props) {

    console.log('LoginPage props are:');
    console.log({ props });

    return (<div className="LoginPage">props are: {props}</div>)
}

function SplashPage(props) {
    const [currentUser, setCurrentUser] = useState(null);

    console.log('SplashPage props are:');
    console.log({ props });

    const userUrl = 'http://localhost:8000/rest-auth/user/';
    console.log('userUrl is:' + userUrl);
    axios.get(userUrl)
        .then(res => { setCurrentUser(res.data); })
        .catch((error) => {
            console.log(error.response);
            return (<div><LoginPage /></div>);
        })
    return (<div className="SplashPage">[{userUrl}] [{currentUser}] </div>);

}


function App() {
    return (
    <div>
      <SplashPage />
    </div>
  );
}

export default App;

这是我的 index.js 文件:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: 
serviceWorker.unregister();

当我去http://localhost:3000我得到这个结果:

在此处输入图像描述

在开发者控制台中看起来像

在此处输入图像描述

我曾希望看到我的LoginPage功能的内容。

标签: djangoreactjsaxios

解决方案


[更新答案]

<div className="SplashPage">[{userUrl}] [{currentUser}] </div>之前返回<div><LoginPage /></div>是因为它在 axios .then() 链之外(即它直接在 axios.get() 之后和 .then() 或 .catch() 块中的任何代码之前调用)

应该管用:

  • 使用 loaderState 初始化当前用户以避免内容闪烁
  • 在 axios .then() 或 .catch() 中更新状态
  • 使用 state 来确定从 promise 之外的函数返回什么

-

function SplashPage(props) {
    const [currentUser={notLoaded:true}, setCurrentUser] = useState(null);
    const userUrl = 'http://localhost:8000/rest-auth/user/';
    axios.get(userUrl).then(res => { 
        setCurrentUser(res.data); 
    }).catch((error) => {
        console.log(error)
        setCurrentUser(null)
    })

    //user no authorized
    if(!currentUser)
        return <LoginPage />
    //user authorization unknown
    if(currentUser.notLoaded)
        return <div/>

    //we have a user!
    return <div className="SplashPage">{userUrl} {currentUser}</div>

}

[原始答案]

编辑:对不起,我误解了你的问题,但会在这里留下我原来的答案,以防有人来寻找相关问题。

您收到 403 错误消息:

未提供身份验证凭据

您需要为您的请求添加某种授权(请参阅您的 django-rest-auth 配置/文档,了解它如何期望来自传入请求的授权)。

您可以手动为每个 api 调用进行设置,也可以通过 axios.interceptors.request.use() 进行设置,您需要在应用程序的某处导入和调用(例如在 app.js 或 index.js 中)

下面的例子:

  • 使用 axios.interceptors
  • 将授权令牌添加到 Authorization 标头
  • 使用标准的“不记名令牌”
  • 使用 firebase auth 演示通过异步检索令牌

(您的实际实施将取决于您的 api 的设置方式和您的授权流程)

addAuthHeader.js:

import axios from 'axios';
import * as firebase from 'firebase/app';

const apiUrl = 'http://localhost:8000/' // '/' if using the preferred http-proxy-middleware

export default addAuthHeader = () => 
    //if firebase auth callback should be asyncasync
    axios.interceptors.request.use(async (config) => {
      if(config.url.startsWith(apiUrl)){
          const token = await firebase.auth().currentUser.getIdToken(true) 
          config.headers.Authorization = `bearer ${token}`;
          return config;
      }
    });

应用程序.js:

addAuthHeader()

推荐阅读