Home > Mobile >  Handle Error With Axios Async/Await in React
Handle Error With Axios Async/Await in React

Time:12-04

I'm using Axios to fetch some data:

export const getProducts = async () => {
   try {
       const { data } = await axios.get(`/api/products`)
       return data
   } catch (err) {
       console.log(err)
       return err
   } 
}

Everything is fine, but I need to catch http errors inside try block. For example, when connection with the server is lost, Axios returns an AxiosError object:

  1. AxiosError {message: 'Request failed with status code 404', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
  2. code: "ERR_BAD_REQUEST"
  3. config: {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
  4. message: "Request failed with status code 404"
  5. name: "AxiosError"
  6. request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
  7. response: {data: '\n\n\n<meta char…re>Cannot GET /api/prducts\n\n\n', status: 404, statusText: 'Not Found', headers: AxiosHeaders, config: {…}, …}
  8. stack: "AxiosError: Request failed with status code 404\n at settle (webpack-internal:///./node_modules/axios/lib/core/settle.js:24:12)\n at XMLHttpRequest.onloadend (webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:117:66)"
  9. [[Prototype]]: Error

The problem is: I want to render a div saying "There was an error fetching the data" if there is an error. If not, render a table with products as usual.

I call my function like this:

const productsArr = await getProducts()

How can I recognize if productsArr is a valid product array, or an AxiosError?

CodePudding user response:

You can see in the official docs how to handle errors: https://axios-http.com/docs/handling_errors

To see the error if no response was received (copied from the axios docs)

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

You can wrap your component with an error-handling boundary. You can either create your component which will wrap your other component in which the error occurs using the componentDidCatch lifecycle method, which is the same as using catch{} inside try-catch https://reactjs.org/docs/react-component.html#componentdidcatch. Or use a popular npm package https://www.npmjs.com/package/react-error-boundary

CodePudding user response:

I used this structure for fetching:

export const getProducts = async () => {

try { const { data } = await axios.get(/api/products) return data } catch (err) { console.log(err) return err } }

I deleted the return in the catch block. So if an error happens, it returns undefined.

I imported getProducts to my component. I did the fetching like this:

useEffect(() => {
    (async function () {
        const productsArr = await getProducts()
        if (productsArr) {
            setProducts(productsArr)
            setLoading(false)
        } else {
            setLoading(false)
            setError(true)
        }
    })()
}, [])

So, I use conditional to validate if productsArr exist. If there was an error, since the fetching returns undefined, I activate setError(true).

It is not the best solution, because I lose access to the error data. I hope there is a better solution.

  • Related