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:
useSWR: The primary hook for data fetching.useSWRHandler: The internal handler encapsulating the detailed hook logic.SWRConfig: The configuration provider for global SWR options.unstable_serialize: Utility for serializing keys (re-exported).
Key Functionalities and Features
Key serialization: Converts arbitrary keys into stable cache keys.
Cache management: Reads, writes, and subscribes to cache state changes.
Revalidation control: Handles when and how to re-fetch data based on configuration and app state.
Concurrency and deduplication: Avoids duplicated requests for the same key.
Error handling and retry logic: Supports retrying failed requests with backoff.
Suspense integration: Supports React Suspense by throwing promises during data fetching.
Global event subscriptions: Reacts to window focus, reconnect, and mutation events to trigger revalidation.
Polling support: Allows periodic background revalidation.
Exposes reactive state: Returns
data,error,isValidating,isLoading, andmutateAPI.
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>
Parameters:
_key: The key identifying the resource to fetch. Can be string, array, or function.fetcher: The function to fetch the data, accepting the key arguments.config: Configuration options for caching, revalidation, suspense, deduplication, etc.
Returns:
An
SWRResponseobject with reactive properties:data: The current cached or fallback data.error: Any error encountered during fetch.isValidating: Whether a fetch is currently in progress.isLoading: Whether the data is loading for the first time.mutate: Function to manually mutate or revalidate the cache.
Functionality Breakdown
Key and Argument Serialization
Uses
serializeto convert_keyinto a stable stringkeyand argumentsfnArgfor the fetcher.Cache Helpers Setup
Creates cache accessors (
getCache,setCache,subscribeCache,getInitialCache) scoped tokey.Initial State and Refs
Tracks mount/unmount state to avoid side effects after unmount.
Maintains refs for
key,fetcher, andconfigto access latest values in async callbacks.Tracks dependencies accessed in state to optimize re-renders.
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.
Cache Snapshot and Subscription
Uses
useSyncExternalStorewith 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.
Data Calculation with Laggy Data Support
Supports
keepPreviousDataconfig to maintain previous data while loading new data.Resolves the actual data to return, falling back to fallback data if cache is empty.
Initial Revalidation Control
Determines if initial revalidation should run based on config, previous data, suspense mode, and pause state.
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.
Mutate Function
A stable
mutatefunction bound to the currentkeyandcache, allowing manual cache updates and revalidation.
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
refreshIntervalis configured.
Debugging Support
Uses React's
useDebugValueto show the current data in React DevTools.
Returned Response Object
Returns an object with reactive getters for
data,error,isValidating,isLoadingthat track dependencies for optimal re-renders.Includes the
mutatemethod.
useSWR
A wrapper created by
withArgsarounduseSWRHandlerthat provides the public API for the hook.Accepts flexible arguments and forwards to the internal handler.
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
A React context provider for global SWR configuration.
Exposes
defaultValuewithdefaultConfigsettings.Allows configuring global options like deduplication interval, retries, suspense, etc.
Internal Utilities and Constants
use: A React experimental utility for suspense handling of promises.WITH_DEDUPE: Option object{ dedupe: true }used in revalidation calls.resolvedUndef: A resolved promise of a sentinelUNDEFINEDvalue, used as a no-op suspense value.Various imported utilities from
../_internalfor cache helpers, serialization, global state, event subscriptions, and more.
Important Implementation Details
Concurrency Control
Requests are tracked with timestamps stored in a global
FETCHobject keyed by cache key. This allows ignoring outdated responses when newer requests are made.Deduplication
If a request for the same key is already ongoing, repeated requests within the deduplication interval reuse the same promise to avoid redundant network requests.
Global Event Subscription
The hook listens to global events such as:
focus: Revalidates when window/tab gains focus.reconnect: Revalidates on network reconnect.mutate: Triggers revalidation after mutations.error-revalidate: Retries after errors.
Suspense Support
The hook throws promises in suspense mode when data is missing or loading, allowing React Suspense boundaries to handle loading states.
Polling
Uses
setTimeoutto schedule periodic revalidations respecting visibility and connectivity.State Dependency Tracking
Uses a mutable
stateDependenciesobject to track which parts of the state are accessed by the component, optimizing subscriptions and re-rendering.
Interaction with Other Parts of the System
Cache Layer (
SWRGlobalState)The hook interacts with a global cache and state management system that stores data, errors, validation status, mutation states, and event revalidators.
Configuration Provider (
SWRConfig)Allows global configuration and default values to be shared across all SWR hooks.
Mutation Utilities
The
mutatefunction uses internal mutation helpers to update the cache and optionally revalidate.Serialization Utilities
Key serialization ensures complex keys are transformed into stable strings for cache indexing.
React Experimental Features
Uses React experimental
useAPI for suspense promise handling.
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:
It balances immediate UI responsiveness via cached data with background revalidation for freshness.
Manages complex concurrency, deduplication, and race conditions for overlapping requests.
Supports React Suspense and error boundaries for declarative loading and error UI.
Listens to global events (focus, reconnect) to auto-refresh data.
Supports polling and manual mutation APIs.
Integrates deeply with a global cache and configuration context.
This implementation is foundational to the SWR ecosystem and enables the developer-friendly, performant data fetching experience SWR is known for.