Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle Error response React.js

My Spring boot Controller method:

@RequestMapping(value = "/test",  method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<APIResponseMessage> testMethod(@RequestBody MyPojo myPojo) {
        APIResponseMessage resp = new APIResponseMessage();
        try {
            serviceObj.callServiceMethod(myPojo);
            resp.setMessage("successfull!");
        } catch (Exception e) {
            resp.setMessage("failed!");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }
        return ResponseEntity.ok(resp);
    }

React action handler class has the following method:

export default (data) => (dispatch) => {
  dispatch({
    type: initHandler
  });

  fetchJSON(url, 'POST', data)
    .then((json) => {
      dispatch({
        type: successHandler,
        apiResponse: json
      })
    })
    .catch((error) => {
      dispatch({
        type: failureHandler,
        apiResponse: error,
        apiMessage : "System encountered error. Please try again later."
      })
    })
}

And fetchJSON is define in one of my util classes in react as :

export const checkStatus = response => {
  const hasError = (response.status < 200 || response.status >= 300)
  if (hasError) {
    const error = new Error("This is an error") // I want to set my message that I obtained from the controller here.
    throw error
  }
  return response
}

export const parseJSON = response => response.json()

export const fetchJSON = (url, method, data) => {
  return fetch(url, {
    method: method,
    headers: new Headers({
      'Content-Type': 'application/json'
    }),
    body: JSON.stringify(data)
  }).then(checkStatus).then(parseJSON);
}

I want to set the custom message that I get from my API to be set to the error object. I tried many options but couldn't make it to work.

like image 779
saupan Avatar asked Apr 01 '26 15:04

saupan


1 Answers

The problem is how the Promise is being resolved, or rather, not resolved when you try to use it. Calls to 'response.json()' return a promise, during the normal flow of execution when you don't 'throw' an error, this promise is resolved, and you can work with the result.

However, when the error is thrown, you need to resolve, or '.then()' the error in the catch block.

I think this should work for you, first throw your response.text() in the checkStatus function:

if (hasError) {
    throw response.json()
}

Since you are throwing an error in a Promise, the nearest catch, or rejection callback is invoked:

.catch((error) => {
  dispatch({
    type: failureHandler,
    apiResponse: error,
    apiMessage : "System encountered error. Please try again later."
  })
})

'error' in this case is the unresolved Promise created by calling 'response.text()', so you can resolve this by wrapping the 'dispatch' in error.then() as follows:

.catch((error) => { // error is a Promise
    error.then((e) => {
        dispatch({
          type: failureHandler,
          apiResponse: e, // e is now the resolved value of 'response.text()'
          apiMessage : "System encountered error. Please try again later."
        });
    });
})

There is a simplified jsfiddle of this here: https://jsfiddle.net/LLL38vea/

like image 190
Finbarr O'B Avatar answered Apr 04 '26 04:04

Finbarr O'B