Rooks
Browser APIs

useFetch

Hook for fetching data from URLs with loading states, error handling, and automatic JSON parsing

useFetch

A hook for fetching data from URLs with proper TypeScript generics, error handling, and automatic JSON parsing. It manages loading states and provides a fetch function for manual data fetching.

Note: This hook does not automatically fetch on mount. You must call the returned startFetch function to trigger the request.

Usage

import { useFetch } from "rooks";
import { useEffect } from "react";
 
function UserProfile({ userId }: { userId: string }) {
  const {
    data: user,
    loading,
    error,
    startFetch,
  } = useFetch<User>(`https://api.example.com/users/${userId}`, {
    headers: { Authorization: "Bearer token" },
    onSuccess: (data) => console.log("User loaded:", data),
    onError: (error) => console.error("Failed to load user:", error),
    onFetch: () => console.log("Fetching user data..."),
  });
 
  // Fetch data when component mounts
  useEffect(() => {
    startFetch();
  }, [startFetch]);
 
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!user) return <div>No user data</div>;
 
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
      <button onClick={startFetch}>Refresh</button>
    </div>
  );
}

Advanced Usage

POST Request with Body

function CreateUser() {
  const {
    data: newUser,
    loading,
    error,
    startFetch,
  } = useFetch<User>("https://api.example.com/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer token",
    },
    body: JSON.stringify({
      name: "John Doe",
      email: "john@example.com",
    }),
    onSuccess: (data) => {
      console.log("User created successfully:", data);
      // Navigate to user profile or show success message
    },
    onError: (error) => {
      console.error("Failed to create user:", error);
      // Show error notification
    },
    onFetch: () => {
      console.log("Creating new user...");
      // Show loading indicator
    },
  });
 
  const handleCreateUser = () => {
    startFetch();
  };
 
  if (loading) return <div>Creating user...</div>;
  if (error) return <div>Error: {error.message}</div>;
 
  return (
    <div>
      <button onClick={handleCreateUser}>Create User</button>
      {newUser && (
        <div>
          <h1>User Created</h1>
          <p>Name: {newUser.name}</p>
          <p>Email: {newUser.email}</p>
        </div>
      )}
    </div>
  );
}

DELETE Request

function DeleteUser({ userId }: { userId: string }) {
  const {
    data: result,
    loading,
    error,
    startFetch,
  } = useFetch<{ success: boolean }>(
    `https://api.example.com/users/${userId}`,
    {
      method: "DELETE",
      headers: {
        Authorization: "Bearer token",
      },
      onSuccess: (data) => {
        if (data.success) {
          console.log("User deleted successfully");
          // Remove user from UI or navigate away
        }
      },
      onError: (error) => {
        console.error("Failed to delete user:", error);
        // Show error notification
      },
    }
  );
 
  const handleDeleteUser = () => {
    startFetch();
  };
 
  if (loading) return <div>Deleting user...</div>;
  if (error) return <div>Error: {error.message}</div>;
 
  return (
    <div>
      <button onClick={handleDeleteUser}>Delete User</button>
      {result && (
        <div>
          <h1>User Deleted</h1>
          <p>Success: {result.success ? "Yes" : "No"}</p>
        </div>
      )}
    </div>
  );
}

API Reference

Parameters

ParameterTypeRequiredDescription
urlstringYesThe URL to fetch data from
optionsUseFetchOptionsNoOptional fetch configuration

Return Value

PropertyTypeDescription
dataT | nullThe fetched data or null
loadingbooleanWhether the request is loading
errorError | nullError object if request failed
startFetch() => Promise<void>Function to trigger a fetch

Options

The options object extends the standard RequestInit interface (excluding signal for compatibility):

PropertyTypeDefaultDescription
methodstring'GET'HTTP method
headersRecord<string, string>{}Request headers
bodystring | FormData | URLSearchParams-Request body
cacheRequestCache'default'Cache strategy
credentialsRequestCredentials'same-origin'Credentials policy
modeRequestMode'cors'Request mode
redirectRequestRedirect'follow'Redirect policy
referrerstring-Referrer URL
referrerPolicyReferrerPolicy-Referrer policy
integritystring-Subresource integrity
keepaliveboolean-Keep-alive flag
onSuccess(data: any) => void-Success callback
onError(error: Error) => void-Error callback
onFetch() => void-Fetch start callback

Notes

  • This hook does not cache requests - each call triggers a fresh fetch
  • The hook does not automatically fetch on mount - you must call the startFetch function
  • The hook automatically handles JSON parsing of responses
  • HTTP errors (4xx, 5xx) are thrown as Error objects with status and statusText properties
  • Network errors are properly caught and exposed through the error property
  • The startFetch function returns a Promise that resolves when the request completes
  • TypeScript generics provide full type safety for the fetched data
  • Callbacks are called at appropriate times during the fetch lifecycle:
    • onFetch: Called when the fetch starts (before the request is made)
    • onSuccess: Called when the request succeeds (with the fetched data)
    • onError: Called when the request fails (with the error object)

On this page