reactjs 处理React中的Axios错误

arknldoa  于 2023-02-04  发布在  React
关注(0)|答案(6)|浏览(241)

我有一个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调用是否返回错误?也就是说,处理来自axios承诺的错误的最佳方式是什么?

xxslljrj

xxslljrj1#

使用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);
    });
ewm0tg9j

ewm0tg9j2#

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

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
       }
    });
  }

如果要从API返回承诺,则不应解析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
     }
  }
mutmk8jj

mutmk8jj3#

我的建议是使用React.Error Boundaries的一个前沿特性
这是Dan Abramov使用这个特性的一个例子。在这种情况下,你可以用这个错误边界组件 Package 你的组件。在axios中捕获错误的特殊之处在于你可以使用拦截器来捕获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;

然后,可以用它 Package 根组件传递axios示例

errorHandler(Checkout, api)

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

agyaoht7

agyaoht74#

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

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

它依赖于axios将为成功和失败返回不同的对象这一事实。

8nuwlpux

8nuwlpux5#

来自Yevhenii Herasymchuk的解决方案非常接近我所需要的,但是,我的目标是使用功能组件实现,以便我可以使用Hooks和Redux。
首先,我创建了一个 Package 器:

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;

然后,我 Package 了项目中需要检查axios行为的部分。

<ErrorHandler>
  <MainPage/>
</ErrorHandler>

最后,我在项目中需要的任何地方导入axios示例(http)。
希望它能帮助任何希望有不同方法的人。

wpx232ag

wpx232ag6#

我只是将Yevhenii HerasymchukGeorgeCodeHub的两个答案结合起来,修正了一些错误,并将其移植到React钩子中。

// [project-directory]/src/lib/axios.js

import Axios from 'axios';

const axios = Axios.create({
  baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
  },
  withCredentials: true,
});

export default axios;
// [project-directory]/src/components/AxiosErrorHandler.js

import {useEffect} from 'react';
import axios from '@/lib/axios';

const AxiosErrorHandler = ({children}) => {
  useEffect(() => {
    // Request interceptor
    const requestInterceptor = axios.interceptors.request.use((request) => {
      // Do something here with request if you need to
      return request;
    });

    // Response interceptor
    const responseInterceptor = axios.interceptors.response.use((response) => {
      // Handle response here

      return response;
    }, (error) => {
      // Handle errors here
      if (error.response?.status) {
        switch (error.response.status) {
          case 401:
            // Handle Unauthenticated here
            break;
          case 403:
            // Handle Unauthorized here
            break;
          // ... And so on
        }
      }

      return error;
    });

    return () => {
      // Remove handlers here
      axios.interceptors.request.eject(requestInterceptor);
      axios.interceptors.response.eject(responseInterceptor);
    };
  }, []);

  return children;
};

export default AxiosErrorHandler;

用法:

// Wrap it around your Layout or any component that you want

return (
  <AxiosErrorHandler>
    <div>Hello from my layout</div>
  </AxiosErrorHandler>
);

相关问题