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


useAxios

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

useAxios Hook Demo

Demonstrando as funcionalidades do hook useAxios com provider global, retry automático, abort controller e múltiplas requisições.

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

Installation

Usage

Wrap your app with AxiosProvider

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

Use the hook in your components

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

API Reference

AxiosProvider Props

PropTypeDefaultDescription
configAxiosConfig{}Global configuration for all axios requests
childrenReactNodeundefinedChild components that will use the provider

AxiosConfig Interface

PropertyTypeDefaultDescription
baseURLstringundefinedBase URL for all relative requests
timeoutnumberundefinedRequest timeout in milliseconds
retriesnumber0Number of retry attempts on failure
retryDelaynumber1000Delay between retry attempts (ms)
headersRecord<string, string>undefinedDefault headers for all requests
methodstring'GET'Default HTTP method
authAxiosBasicCredentialsundefinedBasic authentication credentials
paramsanyundefinedDefault URL parameters
dataanyundefinedDefault request body

useAxios Hook

function useAxios<T>(
  config: AxiosRequestConfig & { immediate?: boolean },
): AxiosResult<T>;

Parameters

ParameterTypeDefaultDescription
configAxiosRequestConfig & { immediate?: boolean }{}Axios configuration and hook options

AxiosOptions Interface

PropertyTypeDefaultDescription
retriesnumberundefinedRetry attempts (overrides global)
retryDelaynumberundefinedRetry delay (overrides global)
immediatebooleantrueWhether to execute request immediately
urlstringundefinedRequest URL
methodstringundefinedHTTP method
dataanyundefinedRequest body
paramsanyundefinedURL parameters
headersRecord<string, string>undefinedRequest headers

Return Value (AxiosResult)

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

Convenience Hooks

useAxiosGet

function useAxiosGet<T>(url: string, config?: AxiosOptions): AxiosResult<T>;

useAxiosPost

function useAxiosPost<T>(
  url: string,
  data?: any,
  config?: AxiosOptions,
): AxiosResult<T>;

useAxiosPut

function useAxiosPut<T>(
  url: string,
  data?: any,
  config?: AxiosOptions,
): AxiosResult<T>;

useAxiosDelete

function useAxiosDelete<T>(url: string, config?: AxiosOptions): AxiosResult<T>;

useAxiosPatch

function useAxiosPatch<T>(
  url: string,
  data?: any,
  config?: AxiosOptions,
): AxiosResult<T>;

useAxiosContext Hook

function useAxiosContext(): AxiosContextValue;

Access the global axios configuration and update it dynamically.

Return Value

PropertyTypeDescription
configAxiosConfigCurrent global configuration
updateConfig(config: Partial<AxiosConfig>) => voidFunction to update global configuration
instanceAxiosInstanceAxios instance
request<T>(config: AxiosRequestConfig) => Promise<AxiosResponse<T>>Enhanced axios request function

useAxiosInstance Hook

function useAxiosInstance(): AxiosInstanceMethods;

Access axios instance methods for manual requests.

Return Value

PropertyTypeDescription
instanceAxiosInstanceRaw axios instance
request<T>(config: AxiosRequestConfig) => Promise<AxiosResponse<T>>Enhanced request function
get<T>(url: string, config?: AxiosRequestConfig) => Promise<AxiosResponse<T>>GET request method
post<T>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<AxiosResponse<T>>POST request method
put<T>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<AxiosResponse<T>>PUT request method
delete<T>(url: string, config?: AxiosRequestConfig) => Promise<AxiosResponse<T>>DELETE request method
patch<T>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<AxiosResponse<T>>PATCH request method

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 and cancellations)
  • 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

🔧 Axios Integration

  • Full Axios feature support (interceptors, transformers, etc.)
  • Request/response transformations
  • Built-in JSON parsing and serialization

Examples

Basic GET Request

const { data, loading, error } = useAxiosGet<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,
} = useAxiosPost<Post>(
  '/posts',
  {
    title: 'New Post',
    body: 'Post content',
    userId: 1,
  },
  {
    immediate: false,
  },
);
 
return (
  <button onClick={createPost} disabled={loading}>
    {loading ? 'Creating...' : 'Create Post'}
  </button>
);

Manual Requests with useAxiosInstance

const { get, post, loading } = useAxiosInstance();
 
const handleFetch = async () => {
  try {
    const response = await get<User[]>('/users');
    console.log(response.data);
  } catch (error) {
    console.error('Request failed:', error);
  }
};
 
return <button onClick={handleFetch}>Fetch Users</button>;

With Retry and Timeout

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

Abort Request

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

Dynamic Configuration

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

Form Submission

function UserForm() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  const {
    data,
    loading,
    error,
    refetch: submitForm,
  } = useAxiosPost<User>('/users', formData, { immediate: false });
 
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    await submitForm();
  };
 
  return (
    <form onSubmit={handleSubmit}>
      <input
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Name"
      />
      <input
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Email"
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Submitting...' : 'Submit'}
      </button>
      {error && <div>Error: {error.message}</div>}
      {data && <div>Success! User ID: {data.id}</div>}
    </form>
  );
}

Error Handling

const { data, error, refetch } = useAxiosGet<Data>('/api/data');
 
if (error) {
  return (
    <div>
      <h3>Request Failed</h3>
      <p>Status: {error.response?.status}</p>
      <p>Message: {error.message}</p>
      <button onClick={refetch}>Retry</button>
    </div>
  );
}

Best Practices

Provider Configuration

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

Loading States

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

Stable Dependencies

const requestData = useMemo(
  () => ({
    userId: user.id,
    timestamp: Date.now(),
  }),
  [user.id],
);
 
const { data, loading } = useAxiosPost<Response>('/api/submit', requestData, {
  immediate: false,
});

Authentication

function useAuth() {
  const { updateConfig } = useAxiosContext();
 
  const login = (token: string) => {
    updateConfig({
      headers: { Authorization: `Bearer ${token}` },
    });
  };
 
  const logout = () => {
    updateConfig({
      headers: {},
    });
  };
 
  return { login, logout };
}