在 React 中处理 Axios 错误

Handling Axios error in React

我有一个调用函数的 React 组件 getAllPeople:

componentDidMount() {
   getAllPeople().then(response => {
      this.setState(() => ({ people: response.data }));
    });
  } 

getAllPeople 在我的 api 模块中:

export function getAllPeople() {
  return axios
    .get("/api/getAllPeople")
    .then(response => {
      return response.data;
    })
    .catch(error => {
      return error;
    });
}

我认为这是一个非常基本的问题,但假设我想在我的根组件(在我的 componentDidMount 方法中)而不是在 api 函数中处理错误,这怎么办根组件知道我axios调用returns是否出错吗? IE。处理来自 axios 承诺的错误的最佳方法是什么?

您可以在将其设置为 state 之前检查响应。像

componentDidMount() {
   getAllPeople().then(response => {
       // check if its actual response or error
        if(error) this.setState(() => ({ error: response }));
        else this.setState(() => ({ people: response}));
    });
  }

它依赖于 axios 将 return 不同的对象作为成功和失败的事实。

getAllPeople 函数已经 return 发送了来自您的 axios 调用的数据或错误消息。因此,在 componentDidMount 中,您需要检查对 getAllPeople 的调用的 return 值,以确定 returned 是错误还是有效数据。

componentDidMount() {
   getAllPeople().then(response => {
      if(response!=error) //error is the error object you can get from the axios call
         this.setState(() => ({ people: response}));
      else { // your error handling goes here
       }
    });
  } 

如果您想 return 来自您的 api 的承诺,您不应该解决 return 由 api 中的 axios 调用编辑的承诺].相反,您可以执行以下操作:

export function getAllPeople() {
  return axios.get("/api/getAllPeople");
}

那你可以在componentDidMount.

中解决
componentDidMount() {
   getAllPeople()
   .then(response => {          
         this.setState(() => ({ people: response.data}));
     })
   .catch(error => { 
         // your error handling goes here
     }
  } 

我的建议是使用 React 的一个前沿特性。 Error Boundaries

这是 Dan Abramov 使用此功能的 example。 在这种情况下,您可以使用此错误边界组件包装您的组件。 在 axios 中捕捉错误的特别之处在于你可以使用 interceptors 用于捕获 API 错误。 您的错误边界组件可能看起来像

import React, { Component } from 'react';

const errorHandler = (WrappedComponent, axios) => {
  return class EH extends Component {
    state = {
      error: null
    };

    componentDidMount() {
      // Set axios interceptors
      this.requestInterceptor = axios.interceptors.request.use(req => {
        this.setState({ error: null });
        return req;
      });

      this.responseInterceptor = axios.interceptors.response.use(
        res => res,
        error => {
          alert('Error happened');
          this.setState({ error });
        }
      );
    }

    componentWillUnmount() {
      // Remove handlers, so Garbage Collector will get rid of if WrappedComponent will be removed 
      axios.interceptors.request.eject(this.requestInterceptor);
      axios.interceptors.response.eject(this.responseInterceptor);
    }

    render() {
      let renderSection = this.state.error ? <div>Error</div> : <WrappedComponent {...this.props} />
      return renderSection;
    }
  };
};

export default errorHandler;

然后,您可以用它包装传递 axios 实例的根组件

errorHandler(Checkout, api)

因此,您根本不需要考虑组件内部的错误。

使用 Promise catch 方法处理 API 错误的更好方法*.

axios.get(people)
    .then((response) => {
        // Success
    })
    .catch((error) => {
        // Error
        if (error.response) {
            // The request was made and the server responded with a status code
            // that falls out of the range of 2xx
            // console.log(error.response.data);
            // console.log(error.response.status);
            // console.log(error.response.headers);
        } else if (error.request) {
            // The request was made but no response was received
            // `error.request` is an instance of XMLHttpRequest in the 
            // browser and an instance of
            // http.ClientRequest in node.js
            console.log(error.request);
        } else {
            // Something happened in setting up the request that triggered an Error
            console.log('Error', error.message);
        }
        console.log(error.config);
    });

Yevhenii Herasymchuk 的解决方案非常接近我的需要,但是,我的目标是使用功能组件实现,以便我可以使用 Hooks 和 Redux。

首先我创建了一个包装器:

export const http = Axios.create({
    baseURL: "/api",
    timeout: 30000,
});

function ErrorHandler(props) {

useEffect(() => {
    //Request interceptor
    http.interceptors.request.use(function (request) {
        // Do something here with Hooks or something else
        return request;
    });

    //Response interceptor
    http.interceptors.response.use(function (response) {
        if (response.status === 400) {
            // Do something here with Hooks or something else
            return response;
        }
        return response;
    });
}, []);

return props.children;
}

export default ErrorHandler;

然后我包装了我需要检查 axios 行为的项目部分。

<ErrorHandler>
  <MainPage/>
</ErrorHandler>

最后,我在项目中需要的地方导入了axios实例(http)。

希望它能帮助任何希望采用不同方法的人。