Reputation: 109
I'm following a react tutorial about handling fetch errors on YouTube. I did exactly what the instructor did but for some reason the catch method is not catching the throw error message. Here's the code:
const Home = () => {
const [blogs, setBlogs] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setTimeout(() => {
fetch("http://localhost:8000/blogs")
.then((res) => {
if (!res.ok) {
throw Error("This error is not getting caught");
}
return res.json();
})
.then((data) => {
setBlogs(data);
setIsPending(false);
setError(null);
})
.catch((err) => {
setIsPending(false);
setError(err.message);
});
}, 1000);
}, []);
return (
<div className="home">
{error && <div>{error} </div>}
{isPending && <div>Loading...</div>}
{blogs && <BlogList blogs={blogs} title="All Blogs!" />}
</div>
);
};
export default Home;
Note: the server is not running.
Upvotes: 0
Views: 1229
Reputation: 370679
The first .then
from fetch
will be entered into when the response headers are received. The response headers may indicate that there's a problem - if the response isn't .ok
- in which case your throw Error
will be entered into as desired and send control flow down to the lower .catch
.
But if no response headers are received at all, the first .then
will not be entered into - instead, a network error will cause a rejection and the .catch
below will be entered into directly.
Your code results in Failed to fetch
being displayed, since that's the error message from a failed request that doesn't even get any headers back:
const { useState, useEffect } = React;
const Home = () => {
const [blogs, setBlogs] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setTimeout(() => {
fetch("http://localhost:8000/blogs")
.then((res) => {
if (!res.ok) {
throw Error("This error is not getting caught");
}
return res.json();
})
.then((data) => {
setBlogs(data);
setIsPending(false);
setError(null);
})
.catch((err) => {
setIsPending(false);
setError(err.message);
});
}, 1000);
}, []);
return (
<div className="home">
{error && <div>{error} </div>}
{isPending && <div>Loading...</div>}
{blogs && <BlogList blogs={blogs} title="All Blogs!" />}
</div>
);
};
ReactDOM.render(<Home />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
If you wanted to have This error is not getting caught
displayed in this sort of situation too, change
setError(err.message);
to
setError('This error is not getting caught');
Upvotes: 5