简体   繁体   中英

Propagate function error from parent component to child component in React while making API request

I have a common post request function where I am fetching data and returning the data to the calling function. And this function is being passed on to other component as prop.

Now If I get an error while fetching the data I want to send the same err to the final component redux so that i can show the error in that component accordingly.

export const post = async (url, payload) => {
  const data = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(payload),
    headers
  })
    .then(res => {
      return res.json()
    })
    .catch(err => {
      throw err
    })
  return data
}

Here ParentFunction is present in parent component and this is being passed as prop to child component.

function ParentFunction(url, payload) {
  postRequest(url, payload).then()
    .catch()
}

and passing this function reference as:

<ChildComponent fetch={this.fun1} />

This is the function in my child component redux where currently I am getting the data as long as I am not getting the error from post request

function fun2() {
  this.props.fetch.then(data => dispatch(....))
  // doing something with this data 
}

Now If I get an error from post request I am passing the same from parent to this function but this fun2 throws an error saying fun1.then is not a function. So how am I supposed the catch the error here also. I tried with fun1.then().catch() but it is not working.

Is there any way that I can achieve this ??

TL;DR:

How do I wrap fetch call in Promise so that I can use .catch when it throws error ?

Let me explain to you the error you are getting.

You're using async/await which returns you the result (not a promise) and when there is an exception, it throws.

Since it is not a promise, it doesn't give you .then or .catch to work with.

One way to achieve what you're trying to do is, call the function, wrap the call between try/catch block and you're good to go. You'll get the data as a result of the function call or you'll get the error in the catch block. Based on that you can handle how you want to pass them to props.

Sample example:

export const post = async (url, payload) => {
  const data = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(payload),
    headers
  })
    .then(res => {
      return res.json()
    })
    .catch(err => {
      throw err
    })
  return data
}

Now while calling it:

let data = null;
let error = null;
try {
  data = post(url, payload)
} catch (e) {
  error = e;
}

Another way would be to return an array as a result. A basic structure could be [err, data] . If you successfully get the data, return [null, data] . If you get an exception, return [err] .

Sample example:

export const post = async (url, payload) => {
  const data = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(payload),
    headers
  })
    .then(res => {
      return [null, res.json()]
    })
    .catch(err => {
      return [err]
    })

  return data
}

Or, you can simply use promises where you can use the usual .then and .catch that you are trying already.

Here is sample example for this:

export const post = (url, payload) => {
      return fetch(url, {
        method: 'POST',
        body: JSON.stringify(payload),
        headers
      })
        .then(res => {
          return res.json()
        }) // as you will be catching the exception later, we can exclude catch from here...
    }

Here is how you call it:

post(url, payload)
  .then((data) => {
    // handle data
  })
  .catch((err) => {
    // handle error
  })

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM