I'm using React 17. I want to submit a fetch request and parse the error JSON that comes back in the event of a 400. I have this code
fetch(REACT_APP_PROXY + "/save_to_sheet_from_form/", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: formData,
})
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw response;
}
})
.then(function (data) {
window.location.reload();
})
.catch((err) => {
err.json().then((errorMessage) => {
try {
setErrors(JSON.parse(errorMessage));
} catch (e) {
return;
}
});
});
In my network tab, I can see this response when there is a 400
{"coop_name":["This field may not be blank."],"street":["This field may not be blank."],"city":["This field may not be blank."],"zip":["This field may not be blank."],"contact_name":["This field may not be blank."],"contact_email":["This field may not be blank."],"contact_phone":["This field may not be blank."]}
However the above line
err.json().then((errorMessage) => {
is throwing a syntax error. What's the proper way to retrieve the body of the response?
If the response, when not OK, may still be JSON-parseable, then using .json
on it will have the browser attempt to parse the result as JSON.
You need to account for a few separate categories:
.then
will not be entered into at all, and the .catch
will be entered into instead)You can put most of the logic testing for this while parsing the header of the response. Something along the lines of
fetch(REACT_APP_PROXY + "/save_to_sheet_from_form/", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: formData,
})
.then((response) => {
if (response.ok) {
// will succeed unless server logic or your logic is off
return response.json().then((data) => {
window.location.reload();
});
} else if (response.status === 400) {
// will succeed if the server will always respond with JSON with a 400 response
return response.json().then((errorObj) => setErrors(errorObj));
} else {
// there was some other error in the response, such as status 500
setErrors(response.statusText);
}
})
.catch((err) => {
// An unexpected error occurred which was not 400 nor while parsing the response header
setErrors(String(err));
});
If the logic to carry out when the request succeeded or failed isn't entirely trivial, go ahead and use standalone named functions instead to make it more readable instead of putting everything in the first .then
. (eg if (response.ok) { return response.json().then(handleSuccess); }
)