Catch block not updating state in custom useFetch React hook

42 Views Asked by At

I have made the following custom useFetch hook for my Next.js app:

import HTTPMethod from "http-method-enum";
import { useState } from "react";

export default function useFetch() {
    const [data, setData] = useState(null);
    const [error, setError] = useState("");
    const [loading, setLoading] = useState(false);

    

    const sendFetch = async (url: string, method: HTTPMethod, body: any): Promise <any> => {
        try {
            setLoading(true);
            const rawResponse = await fetch(url, {
                method,
                headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    body,
                }),
            });

            const response = await rawResponse.json();
            setData(response);
        } catch (error: any) {
            setError(error);
        } finally {
            setLoading(false);
        }
    };

    return [data, loading, error, sendFetch];
}

Everything is working accept for error handling. My catch block is not triggering even after a 400 error code from fetch. Instead all of the response (whether there is an error or not) is in the data state. When I console the error state outside the catch block I get an empty string. I also don't get anything at all in the catch block.

When there is an error I want the response to be stored in the error state.

Please don't recommend Axios or any other fetch libraries as they run slow on the edge.

Edit:

I changed my code to:

import HTTPMethod from "http-method-enum";
import { useState } from "react";

export default function useFetch() {
    const [data, setData] = useState(null);
    const [error, setError] = useState("");
    const [loading, setLoading] = useState(false);

    console.log(error)

    const sendFetch = async (url: string, method: HTTPMethod, body: any): Promise <any> => {
        try {
            setLoading(true);
            const rawResponse = await fetch(url, {
                method,
                headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    body,
                }),
            });

            const response = await rawResponse.json();

            if (!response.ok) {
                throw new Error(response.message)
            }
            setData(response);
        } catch (error: any) {
            setError(error);
        } finally {
            setLoading(false);
        }
    };

    return [data, loading, error, sendFetch];
}

However my state is not updating. But it will update if you a string value like so: setError("Error"). However when you pass in the error parameter error stays as an empty string.

0

There are 0 best solutions below