kazi siam
kazi siam

Reputation: 109

throw error message is not getting caught by the catch method

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

Answers (1)

CertainPerformance
CertainPerformance

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

Related Questions