useFetch Custom Hook Examples

Overview

The useFetch hook is a custom hook that abstracts the common pattern of fetching data, handling loading states, and managing errors. This hook can be reused across components to fetch different types of data while maintaining consistent behavior and state management.

Example 1: User Profile

This example uses useFetch to retrieve user data:

Loading user data...
Code for UserProfile

Example 2: Posts List

This example uses the same useFetch hook to retrieve a list of posts:

Loading posts...
Code for PostsList

Implementation

// useFetch.tsx
export function useFetch<T>(fetchFunction: () => Promise<T>) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    setLoading(true);
    setError(null);
    
    const fetchData = async () => {
      try {
        const result = await fetchFunction();
        setData(result);
      } catch (err) {
        setError(err instanceof Error ? err : new Error('An error occurred'));
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [fetchFunction]);

  return { data, loading, error };
}

Key Points

  • The hook accepts a fetch function as a parameter, making it reusable for different data sources
  • It handles three states: loading, error, and data
  • Uses TypeScript generics to handle different data types
  • Properly cleans up state between re-renders

Usage Pattern

// Component using useFetch
const MyComponent = () => {
  const { data, loading, error } = useFetch(myFetchFunction);

  if (error) return <div>Error: {error.message}</div>;
  if (loading) return <div>Loading...</div>;
  
  return (
    <div>
      {/* Render data here */}
    </div>
  );
};