use-swr.ts


Overview

The use-swr.ts file contains the core implementation of the useSWR React hook, which provides an efficient, declarative data fetching solution in React applications using the stale-while-revalidate (SWR) strategy. This hook manages caching, background revalidation, concurrency control, error handling, suspense integration, and lifecycle event subscriptions to deliver fresh data with minimal UI blocking and network overhead.

The file exports:


Key Functionalities and Features


Detailed Explanation of Main Entities

useSWRHandler<Data, Error>

The core function implementing the SWR hook logic.

Signature

function useSWRHandler<Data = any, Error = any>(
  _key: Key,
  fetcher: Fetcher<Data> | null,
  config: FullConfiguration & SWRConfiguration<Data, Error>
): SWRResponse<Data, Error>

Functionality Breakdown

  1. Key and Argument Serialization

    Uses serialize to convert _key into a stable string key and arguments fnArg for the fetcher.

  2. Cache Helpers Setup

    Creates cache accessors (getCache, setCache, subscribeCache, getInitialCache) scoped to key.

  3. Initial State and Refs

    • Tracks mount/unmount state to avoid side effects after unmount.

    • Maintains refs for key, fetcher, and config to access latest values in async callbacks.

    • Tracks dependencies accessed in state to optimize re-renders.

  4. Fallback Data and Suspense Support

    • Resolves fallback data from inline or global config.

    • Supports fallback promises to trigger React Suspense.

    • Throws promises or errors in Suspense mode to integrate with React Suspense/ErrorBoundary.

  5. Cache Snapshot and Subscription

    • Uses useSyncExternalStore with a memoized snapshot selector and equality check to subscribe React components to cache changes efficiently.

    • Implements a custom equality function to avoid unnecessary re-renders.

  6. Data Calculation with Laggy Data Support

    • Supports keepPreviousData config to maintain previous data while loading new data.

    • Resolves the actual data to return, falling back to fallback data if cache is empty.

  7. Initial Revalidation Control

    • Determines if initial revalidation should run based on config, previous data, suspense mode, and pause state.

  8. Revalidate Function

    • A memoized async function wrapping the fetcher with robust logic:

      • Deduplicates concurrent requests.

      • Tracks request timestamps to prevent race conditions.

      • Updates cache state for loading, success, error.

      • Handles retry logic on errors.

      • Calls lifecycle callbacks (onSuccess, onError, onDiscarded, onLoadingSlow).

      • Cleans up stale requests.

      • Respects pause state.

  9. Mutate Function

    • A stable mutate function bound to the current key and cache, allowing manual cache updates and revalidation.

  10. Lifecycle Effects

    • Updates refs on every render.

    • Subscribes to global revalidation events (focus, reconnect, mutation, error retry).

    • Triggers initial or deferred revalidation after mount or key changes.

    • Sets up polling if refreshInterval is configured.

  11. Debugging Support

    • Uses React's useDebugValue to show the current data in React DevTools.

  12. Returned Response Object

    • Returns an object with reactive getters for data, error, isValidating, isLoading that track dependencies for optimal re-renders.

    • Includes the mutate method.


useSWR

Example usage:

import useSWR from 'use-swr'

function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetchUser)
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

SWRConfig


Internal Utilities and Constants


Important Implementation Details


Interaction with Other Parts of the System


Usage Example

import useSWR from 'use-swr'

async function fetcher(url: string) {
  const res = await fetch(url)
  if (!res.ok) throw new Error('Failed to fetch')
  return res.json()
}

function Profile() {
  const { data, error, isLoading, isValidating, mutate } = useSWR('/api/user', fetcher)

  if (error) return <div>Error loading user</div>
  if (isLoading) return <div>Loading...</div>

  return (
    <div>
      <p>Hello, {data.name}!</p>
      <button onClick={() => mutate()}>Refresh</button>
      {isValidating && <small>Refreshing...</small>}
    </div>
  )
}

Mermaid Diagram: Structure and Main Workflow of use-swr.ts

flowchart TD
    A[Component calls useSWR] --> B[Serialize key & args]
    B --> C[Setup cache helpers for key]
    C --> D[Subscribe to cache changes (useSyncExternalStore)]
    D --> E{Is data cached?}
    E -- Yes --> F[Return cached data]
    E -- No --> G[Use fallback or suspense promise]
    G --> H[Revalidate function (async)]
    H --> I{Deduplicate & concurrency checks}
    I --> J[Call fetcher]
    J --> K[Update cache with new data or error]
    K --> L[Trigger callbacks: onSuccess/onError etc.]
    L --> M[Notify subscribers & re-render]
    M --> D
    H --> N[Handle retries and error logic]
    N --> L
    subgraph Suspense Mode
      G -- Pending --> O[Throw promise to Suspense]
      N -- Error --> P[Throw error to Error Boundary]
    end

Summary

The use-swr.ts file implements the core useSWR hook that provides an advanced, highly optimized, and configurable data fetching mechanism for React applications:

This implementation is foundational to the SWR ecosystem and enables the developer-friendly, performant data fetching experience SWR is known for.


End of Documentation for use-swr.ts