Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling response status using fetch in react JS

I just started learning ReactJS. Now I want to know how to handle response status when I make an API request using fetch. Here's my code :

componentDidMount(){
    this.setState({ isLoading: true })
    var id = this.props.match.params.id        

    const api = `bla/bla/${id}`;

    console.log("start call api")
    fetch(api)
        .then((response) => {
            if(response.status === 200){
                console.log("SUCCESSS")
                return response.json();     
            }else if(response.status === 408){
                console.log("SOMETHING WENT WRONG")
                this.setState({ requestFailed: true })
            }
        })
        .then((data) => {
            this.setState({ isLoading: false, downlines: data.response })
            console.log("DATA STORED")
        })
        .catch((error) => {
            this.setState({ requestFailed: true })
        })
    console.log("end call api")
}

I turned off my connection to make a test for 408, but my loading is still appears.

render(){
     const { isLoading, requestFailed } = this.state;
      if(requestFailed){
        return( 
            <div className="errorContainer">
                <a className="errorMessage">Opss.. Something went wrong :(</a>
            </div>
        )
    }
}

here's the log in my browser: enter image description here

Any ideas to fix this ?

like image 975
kurniawan26 Avatar asked Apr 09 '18 03:04

kurniawan26


People also ask

How do I get my fetch response status?

To get the status code of an HTTP request made with the fetch method, access the status property on the response object. The response. status property contains the HTTP status code of the response, e.g. 200 for a successful response or 500 for a server error. Copied!

Can I use fetch in React JS?

Using Fetch​React Native provides the Fetch API for your networking needs. Fetch will seem familiar if you have used XMLHttpRequest or other networking APIs before. You may refer to MDN's guide on Using Fetch for additional information.


3 Answers

Throw an error when the response is not OK so that it proceeds directly to the catch:

fetch(api)
  .then((response) => {
    if(!response.ok) throw new Error(response.status);
    else return response.json();
  })
  .then((data) => {
    this.setState({ isLoading: false, downlines: data.response });
    console.log("DATA STORED");
  })
  .catch((error) => {
    console.log('error: ' + error);
    this.setState({ requestFailed: true });
  });
like image 145
CertainPerformance Avatar answered Sep 23 '22 12:09

CertainPerformance


According to MDN documentation:

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

A fetch() promise will reject with a TypeError when a network error is encountered or CORS is misconfigured on the server side, although this usually means permission issues or similar — a 404 does not constitute a network error, for example. An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. The code would look something like this:

fetch('flowers.jpg').then(function(response) {
   if(response.ok) {
     return response.blob();
 }
 throw new Error('Network response was not ok.');
}).then(function(myBlob) { 
   var objectURL = URL.createObjectURL(myBlob); 
   myImage.src = objectURL; 
}).catch(function(error) {
 console.log('There has been a problem with your fetch operation: ', 
 error.message);
});

Looking at your code, I don't think your 408 error check will ever run. I don't think it did in fact. Basically what the code above is doing is returning the json response if the request is 200ish ok, otherwise it's throwing an error. If an error occurs, your second then never runs and it gets thrown to your catch block. Perhaps you can set the isLoading: false there?

Also you're log statement for end of api isn't correct. That's being called before your promise completes.

like image 23
Charles Owen Avatar answered Sep 20 '22 12:09

Charles Owen


If you want to know both the json response and error code in the same return value, I recommend this method:

async function loginUser(credentials) {
  var resp;
  return fetch("http://127.0.0.1:8000/api/token-auth/", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(credentials)
  }).then(response => {
    resp = response;
    return response.json();
  }).then(json => {
    return {
      response: resp,
      json: json,
      error: !resp.ok
    };
  });
}

In this case you will get an array with response, json and error field. This is a better aproach if you use API with per field error messages like this:

{"username":["This field is required."],"password":["This field is required."]}
like image 31
kepes Avatar answered Sep 20 '22 12:09

kepes