JAVASCRIPT

Build a Generic Data Fetching useFetch Custom Hook

Create a versatile `useFetch` custom hook in React for handling data fetching, including loading and error states. Simplify API calls across your application.

import { useState, useEffect } from 'react';

function useFetch(url, options) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      setError(null); // Reset error on new fetch attempt
      try {
        const response = await fetch(url, options);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const result = await response.json();
        setData(result);
      } catch (fetchError) {
        setError(fetchError);
      } finally {
        setLoading(false);
      }
    };

    if (url) { // Only fetch if URL is provided
      fetchData();
    }

    // Cleanup function (optional, but good practice for aborting requests)
    // const abortController = new AbortController();
    // options = { ...options, signal: abortController.signal };
    // return () => abortController.abort(); // Abort fetch on unmount
  }, [url, JSON.stringify(options)]); // Re-run if URL or options change

  return { data, loading, error };
}

// Example usage:
function PostsComponent() {
  const { data: posts, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
  // For a POST request, you might pass options like:
  // const { data: postResult } = useFetch('https://jsonplaceholder.typicode.com/posts', {
  //   method: 'POST',
  //   headers: { 'Content-Type': 'application/json' },
  //   body: JSON.stringify({ title: 'foo', body: 'bar', userId: 1 }),
  // });

  if (loading) return <p>Loading posts...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!posts) return <p>No posts found.</p>;

  return (
    <div>
      <h2>Latest Posts</h2>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <h3>{post.title}</h3>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default PostsComponent;
How it works: The `useFetch` custom hook provides a streamlined way to handle asynchronous data fetching in React components. It manages three key pieces of state: `data` (for the fetched result), `loading` (to indicate ongoing requests), and `error` (for any issues during fetching). The `useEffect` hook performs the actual `fetch` operation, updating these states accordingly. It takes a `url` and optional `options` (like method, headers, body) for the `fetch` API, re-running the fetch whenever these dependencies change. This hook simplifies displaying UI based on the fetch status.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs