CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ahooksjs--use-request

React Hooks for fetching, caching and updating asynchronous data

Pending
Overview
Eval results
Files

core-request.mddocs/

Core Request Management

Core async data fetching functionality with comprehensive state management, caching, request lifecycle control, and advanced features like polling, debouncing, and concurrent request handling.

Capabilities

useRequest (Default Export)

Main hook for data fetching with comprehensive configuration options. Automatically handles request state, caching, polling, and lifecycle management.

/**
 * Main useRequest hook for async data fetching
 * @param service - URL string, request object, or async function
 * @param options - Configuration options for request behavior
 * @returns Request state and control functions
 */
function useRequest<R = any, P extends any[] = any>(
  service: CombineService<R, P>,
  options?: BaseOptions<R, P>
): BaseResult<R, P>;

/**
 * useRequest with response formatting
 * @param service - URL string, request object, or async function  
 * @param options - Configuration options with formatResult function
 * @returns Request state with formatted data
 */
function useRequest<R = any, P extends any[] = any, U = any, UU extends U = any>(
  service: CombineService<R, P>,
  options: OptionsWithFormat<R, P, U, UU>
): BaseResult<U, P>;

Usage Examples:

import useRequest from "@ahooksjs/use-request";

// Simple URL string
const { data, loading, error } = useRequest('/api/users');

// Function service with parameters
const { data, loading, run } = useRequest(
  (id: string) => `/api/user/${id}`,
  { manual: true }
);
run('123');

// Request object
const { data, loading } = useRequest({
  url: '/api/users',
  method: 'POST',
  body: JSON.stringify({ name: 'John' }),
  headers: { 'Content-Type': 'application/json' }
});

// Async function service
const { data, loading } = useRequest(async (query: string) => {
  const response = await fetch(`/api/search?q=${query}`);
  return response.json();
});

// With response formatting
const { data, loading } = useRequest('/api/user', {
  formatResult: (response) => ({
    id: response.data.id,
    name: response.data.full_name,
    email: response.data.email_address
  })
});

useAsync

Core async hook handling basic data fetching, caching, and state management. This is the underlying implementation used by useRequest.

/**
 * Core async data fetching hook
 * @param service - Async function to execute
 * @param options - Configuration options
 * @returns Request state and control functions
 */
function useAsync<R, P extends any[]>(
  service: Service<R, P>,
  options?: BaseOptions<R, P>
): BaseResult<R, P>;

/**
 * useAsync with response formatting
 * @param service - Async function to execute
 * @param options - Configuration options with formatResult
 * @returns Request state with formatted data
 */
function useAsync<R, P extends any[], U, UU extends U = any>(
  service: Service<R, P>,
  options: OptionsWithFormat<R, P, U, UU>
): BaseResult<U, P>;

Usage Examples:

import { useAsync } from "@ahooksjs/use-request";

// Basic usage
const { data, loading, error, run } = useAsync(
  async (userId: string) => {
    const response = await fetch(`/api/user/${userId}`);
    return response.json();
  },
  { manual: true }
);

// Execute the async function
run('123');

Configuration Options

Basic Configuration

interface BaseOptions<R, P extends any[]> {
  /** Dependencies that trigger refresh */
  refreshDeps?: DependencyList;
  /** Manual trigger mode - prevents automatic execution */
  manual?: boolean;
  /** Success callback */
  onSuccess?: (data: R, params: P) => void;
  /** Error callback */
  onError?: (e: Error, params: P) => void;
  /** Initial loading state */
  defaultLoading?: boolean;
  /** Delay before showing loading state (ms) */
  loadingDelay?: number;
  /** Default parameters for automatic execution */
  defaultParams?: P;
  /** Initial data value */
  initialData?: R;
  /** Ready state for conditional requests */
  ready?: boolean;
  /** Throw errors instead of catching them */
  throwOnError?: boolean;
}

Polling Configuration

interface PollingOptions {
  /** Polling interval in milliseconds */
  pollingInterval?: number;
  /** Continue polling when window/tab is hidden */
  pollingWhenHidden?: boolean;
}

Usage Examples:

// Polling every 5 seconds
const { data } = useRequest('/api/status', {
  pollingInterval: 5000
});

// Stop polling when window is hidden
const { data } = useRequest('/api/live-data', {
  pollingInterval: 1000,
  pollingWhenHidden: false
});

Window Focus & Visibility

interface FocusOptions {
  /** Refresh when window gains focus */
  refreshOnWindowFocus?: boolean;
  /** Debounce time for focus refresh (ms) */
  focusTimespan?: number;
}

Usage Examples:

// Refresh data when user returns to tab
const { data } = useRequest('/api/notifications', {
  refreshOnWindowFocus: true,
  focusTimespan: 5000 // Don't refresh more than once per 5 seconds
});

Caching Configuration

interface CachingOptions {
  /** Cache key for request caching */
  cacheKey?: CachedKeyType;
  /** Cache expiration time (ms) */
  cacheTime?: number;
  /** Stale data time threshold (ms) */
  staleTime?: number;
}

type CachedKeyType = string | number;

Usage Examples:

// Cache user data for 5 minutes
const { data } = useRequest('/api/user', {
  cacheKey: 'user-profile',
  cacheTime: 5 * 60 * 1000,
  staleTime: 30 * 1000 // Consider stale after 30 seconds
});

// Cache with dynamic key
const { data } = useRequest(
  (userId: string) => `/api/user/${userId}`,
  {
    cacheKey: (userId) => `user-${userId}`,
    cacheTime: 5 * 60 * 1000
  }
);

Request Debouncing & Throttling

interface RateLimitingOptions {
  /** Debounce request execution (ms) */
  debounceInterval?: number;
  /** Throttle request execution (ms) */
  throttleInterval?: number;
}

Usage Examples:

// Debounce API calls for search
const { data, run } = useRequest(
  (query: string) => `/api/search?q=${query}`,
  {
    manual: true,
    debounceInterval: 300 // Wait 300ms after last call
  }
);

// Throttle expensive operations
const { data, run } = useRequest(
  (data: any) => '/api/process',
  {
    manual: true,
    throttleInterval: 1000 // Maximum once per second
  }
);

Concurrent Requests

interface ConcurrentOptions<P extends any[]> {
  /** Generate key for multiple concurrent requests */
  fetchKey?: (...args: P) => string;
}

Usage Examples:

// Handle multiple user requests simultaneously
const { data, run, fetches } = useRequest(
  (userId: string) => `/api/user/${userId}`,
  {
    manual: true,
    fetchKey: (userId) => `user-${userId}`
  }
);

// Execute multiple requests
run('user1');
run('user2');
run('user3');

// Access individual request states
console.log(fetches['user-user1']); // State for user1 request
console.log(fetches['user-user2']); // State for user2 request

Custom Request Method

interface CustomRequestOptions {
  /** Custom request implementation */
  requestMethod?: (service: any) => Promise<any>;
}

Usage Examples:

import axios from 'axios';

// Use axios instead of fetch
const { data } = useRequest('/api/data', {
  requestMethod: (url) => axios.get(url).then(res => res.data)
});

// Custom request with authentication
const { data } = useRequest('/api/secure-data', {
  requestMethod: async (service) => {
    const token = localStorage.getItem('auth-token');
    if (typeof service === 'string') {
      const response = await fetch(service, {
        headers: { Authorization: `Bearer ${token}` }
      });
      return response.json();
    }
    return fetch(service.url, {
      ...service,
      headers: { 
        ...service.headers,
        Authorization: `Bearer ${token}` 
      }
    }).then(res => res.json());
  }
});

Result Interface

BaseResult

The complete result object returned by useRequest and useAsync.

interface BaseResult<R, P extends any[]> extends FetchResult<R, P> {
  /** Reset all request state */
  reset: () => void;
  /** Multiple request instances (when using fetchKey) */
  fetches: {
    [key in string]: FetchResult<R, P>;
  };
}

interface FetchResult<R, P extends any[]> {
  /** Current loading state */
  loading: boolean;
  /** Response data */
  data: R | undefined;
  /** Request error */
  error: Error | undefined;
  /** Request parameters */
  params: P;
  /** Cancel current request */
  cancel: () => void;
  /** Refresh with same parameters */
  refresh: () => Promise<R>;
  /** Mutate data without request */
  mutate: Mutate<R>;
  /** Execute request with parameters */
  run: (...args: P) => Promise<R>;
  /** Cleanup function */
  unmount: () => void;
}

type Mutate<R> = (x: R | undefined | ((data: R) => R)) => void;

Usage Examples:

const { 
  data,           // Current response data
  loading,        // Loading state
  error,          // Error object if request failed
  params,         // Parameters from last request
  run,            // Execute request manually
  refresh,        // Re-execute with same params
  mutate,         // Update data without request
  cancel,         // Cancel ongoing request
  reset,          // Reset all state
  fetches,        // Multiple request states
  unmount         // Cleanup
} = useRequest('/api/data');

// Mutate data optimistically
mutate(currentData => ({
  ...currentData,
  updated: true
}));

// Reset to initial state
reset();

// Refresh current request
refresh();

Error Handling

interface ErrorHandlingOptions<R, P extends any[]> {
  /** Error callback */
  onError?: (e: Error, params: P) => void;
  /** Throw errors instead of catching */
  throwOnError?: boolean;
}

Usage Examples:

// Handle errors with callback
const { data, error } = useRequest('/api/data', {
  onError: (error, params) => {
    console.error('Request failed:', error.message);
    // Log to error tracking service
    errorTracker.log(error, { params });
  }
});

// Throw errors for custom handling
const { data } = useRequest('/api/data', {
  throwOnError: true
});

// Manual error handling with try/catch
const { run } = useRequest(
  (data) => '/api/save',
  { 
    manual: true,
    throwOnError: true 
  }
);

try {
  await run(formData);
  showSuccessMessage();
} catch (error) {
  showErrorMessage(error.message);
}

Lifecycle Management

Component Lifecycle

// Automatic cleanup on unmount
const { data } = useRequest('/api/data', {
  pollingInterval: 1000
}); // Polling stops when component unmounts

// Manual cleanup
const { unmount } = useRequest('/api/data');
useEffect(() => {
  return () => {
    unmount(); // Clean up manually if needed
  };
}, []);

Request Lifecycle

// Conditional requests
const [userId, setUserId] = useState<string>();
const { data } = useRequest(
  () => `/api/user/${userId}`,
  {
    ready: !!userId, // Only execute when userId exists
    refreshDeps: [userId] // Re-execute when userId changes
  }
);

// Dependent requests
const { data: user } = useRequest('/api/user');
const { data: posts } = useRequest(
  () => `/api/posts?userId=${user?.id}`,
  {
    ready: !!user?.id, // Wait for user data
    refreshDeps: [user?.id]
  }
);

Install with Tessl CLI

npx tessl i tessl/npm-ahooksjs--use-request

docs

advanced.md

core-request.md

index.md

load-more.md

pagination.md

tile.json