Data fetching made easy. Check out the new category! 🚀


useFetch

A powerful React hook for HTTP requests with global provider, retry logic, timeout, and abort control

useFetch Hook Demo

Demonstrando as funcionalidades do hook useFetch com provider global, retry automático, timeout e controle de abort. Teste os diferentes tipos de requisição e configurações dinâmicas.

GET Request
Fetches data with a 3-second delay to test abort functionality
Idle

Installation

Usage

Wrap your app with FetchProvider

import { FetchProvider } from '@/hooks/use-fetch';
 
function App() {
  return (
    <FetchProvider config={{ baseURL: 'https://api.example.com' }}>
      <YourApp />
    </FetchProvider>
  );
}

Use the hook in your components

import { useFetch } from '@/hooks/use-fetch';
 
function UserProfile() {
  const { data, loading, error } = useFetch<User>('/users/me');
 
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
 
  return <div>{data?.name}</div>;
}

API Reference

FetchProvider Props

PropTypeDefaultDescription
configFetchConfig{}Global configuration for all fetch requests
childrenReactNodeundefinedChild components that will use the provider

FetchConfig Interface

PropertyTypeDefaultDescription
baseURLstringundefinedBase URL for all relative requests
timeoutnumberundefinedRequest timeout in milliseconds
retriesnumber0Number of retry attempts on failure
retryDelaynumber1000Delay between retry attempts (ms)
headersHeadersInitundefinedDefault headers for all requests
methodstring'GET'Default HTTP method
modeRequestModeundefinedCORS mode
credentialsRequestCredentialsundefinedCredentials mode
cacheRequestCacheundefinedCache mode

useFetch Hook

function useFetch<T, TBody>(
  url: string,
  options?: FetchOptions<TBody> & { immediate?: boolean },
): FetchResult<T>;

Parameters

ParameterTypeDefaultDescription
urlstringundefinedThe endpoint URL to fetch data from
optionsFetchOptions<TBody> & { immediate?: boolean }{}Fetch options and hook configuration

FetchOptions Interface

PropertyTypeDefaultDescription
bodyTBodyundefinedRequest body
timeoutnumberundefinedRequest timeout (overrides global)
retriesnumberundefinedRetry attempts (overrides global)
retryDelaynumberundefinedRetry delay (overrides global)
parse(response: Response) => Promise<any>undefinedCustom response parser
immediatebooleantrueWhether to execute request immediately
headersHeadersInitundefinedRequest headers
methodstringundefinedHTTP method
signalAbortSignalundefinedAbort signal

Return Value (FetchResult)

PropertyTypeDescription
dataT | nullThe fetched data or null on error/loading
errorError | nullError object if the request fails
loadingbooleanWhether the request is in progress
refetch() => Promise<T | null>Function to re-trigger the fetch request
abort() => voidCancels the current in-flight request
abortedbooleanWhether the request was aborted

useFetchContext Hook

function useFetchContext(): FetchContextValue;

Access the global fetch configuration and update it dynamically.

Return Value

PropertyTypeDescription
configFetchConfigCurrent global configuration
updateConfig(config: Partial<FetchConfig>) => voidFunction to update global configuration
fetch(url: string, options?: FetchOptions) => Promise<Response>Enhanced fetch function

Key Features

🌐 Global Provider

  • Centralized configuration for all HTTP requests
  • Shared settings like base URL, headers, timeouts
  • Dynamic configuration updates at runtime

🔄 Automatic Retry

  • Configurable retry attempts with exponential backoff
  • Intelligent retry logic (skips client errors)
  • Per-request or global retry configuration

⏱️ Timeout Support

  • Request-level and global timeout settings
  • Automatic request cancellation on timeout
  • Prevents hanging requests

🛑 Abort Control

  • Manual request cancellation
  • Automatic cleanup on component unmount
  • Prevents memory leaks and race conditions

🎯 Type Safety

  • Full TypeScript support with generics
  • Type-safe request/response handling
  • Intellisense for all configuration options

🚀 Performance

  • Efficient memoization to prevent unnecessary re-renders
  • Automatic request deduplication
  • Optimized for React concurrent features

Examples

Basic GET Request

const { data, loading, error } = useFetch<Post[]>('/posts');
 
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
 
return (
  <div>
    {data?.map((post) => (
      <div key={post.id}>{post.title}</div>
    ))}
  </div>
);

POST Request

const {
  data,
  loading,
  refetch: createPost,
} = useFetch<Post>('/posts', {
  method: 'POST',
  body: JSON.stringify({ title: 'New Post' }),
  immediate: false,
});
 
return (
  <button onClick={createPost} disabled={loading}>
    {loading ? 'Creating...' : 'Create Post'}
  </button>
);

Custom Parser

const { data } = useFetch<{ count: number }>('/stats', {
  parse: (response) =>
    response.text().then((text) => ({ count: parseInt(text) })),
});

With Retry and Timeout

const { data, loading } = useFetch<Data>('/api/data', {
  retries: 3,
  timeout: 5000,
});

Abort Request

const { data, loading, abort } = useFetch<Data>('/api/data');
 
return (
  <div>
    {loading && <button onClick={abort}>Cancel</button>}
    {data && <div>{JSON.stringify(data)}</div>}
  </div>
);

Dynamic Configuration

function AuthButton() {
  const { updateConfig } = useFetchContext();
 
  const handleLogin = (token: string) => {
    updateConfig({
      headers: { Authorization: `Bearer ${token}` },
    });
  };
 
  return <button onClick={() => handleLogin('token')}>Login</button>;
}

Error Handling

const { data, error, refetch } = useFetch<Data>('/api/data');
 
if (error) {
  return (
    <div>
      Error: {error.message}
      <button onClick={refetch}>Retry</button>
    </div>
  );
}

Best Practices

Provider Configuration

<FetchProvider
  config={{
    baseURL: process.env.REACT_APP_API_URL,
    timeout: 30000,
    retries: 3,
    headers: { 'Content-Type': 'application/json' },
  }}
>

Loading States

const { data, loading, error } = useFetch<Data>('/api/data');
 
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
 
return <div>{data?.content}</div>;

Stable Options

const options = useMemo(
  () => ({
    method: 'POST',
    body: JSON.stringify(formData),
  }),
  [formData],
);
 
const { data, loading } = useFetch<Response>('/api/submit', options);