index.ts


Overview

The index.ts file implements the infinite loading middleware for the SWR (stale-while-revalidate) React hook library. Its purpose is to enable efficient, declarative fetching and caching of paginated or infinite lists of data within React applications via the useSWRInfinite hook.

This middleware extends the core useSWR hook by managing multiple page keys, page sizes, and revalidation strategies explicitly designed for infinite scrolling or "load more" UI patterns. It orchestrates individual page data fetching, caching, and revalidation while exposing a unified API to interact with the entire paginated data set as an array.

Key features include:


Detailed Explanation

Main Export: useSWRInfinite

useSWRInfinite is the custom React hook built by composing the core useSWR hook with the infinite loading middleware. It provides an API tailored for infinite or paginated data fetching scenarios.

const useSWRInfinite = withMiddleware(useSWR, infinite) as SWRInfiniteHook
export default useSWRInfinite

Infinite Middleware Function: infinite

This is the core middleware function that adds infinite loading logic on top of a base SWR hook (useSWRNext).

export const infinite = (<Data, Error>(useSWRNext: SWRHook) =>
  (
    getKey: SWRInfiniteKeyLoader,
    fn: BareFetcher<Data> | null,
    config: Omit<typeof SWRConfig.defaultValue, 'fetcher'> &
      Omit<SWRInfiniteConfiguration<Data, Error>, 'fetcher'>
  ) => { ... }
) as unknown as Middleware

Parameters


Returned Object (Infinite Hook API)

The hook returns an object with the following properties and methods:

Property/Method

Type

Description

size

number

Current number of pages loaded.

setSize

`(size: number \

(size: number) => number) => Promise<Data[]> \

mutate

function

Extended mutate function to mutate the cached pages array or trigger revalidation.

data

`Data[] \

undefined`

error

`Error \

undefined`

isValidating

boolean

Indicates whether any page is currently validating (fetching).

isLoading

boolean

Indicates whether the initial loading state is ongoing.


Important Internal Variables and Hooks


Data Fetching Logic (Fetcher in useSWRNext)

The middleware provides a custom fetcher function to useSWRNext that:

  1. Reads the current page size.

  2. Iterates from 0 to pageSize - 1:

    • Calls getKey(i, previousPageData) to get the page key and arguments.

    • If the key is falsy, fetching stops early.

    • Reads cached data for that page.

    • Determines if the page should be revalidated/fetched based on config flags and cache state.

    • If fetching is needed, calls the fetcher function fn or resolves from preload cache if available.

    • Stores the fetched page data in cache.

  3. Supports fetching pages in parallel or sequentially based on the parallel config flag.

  4. Returns an array of page data for all loaded pages.


mutate Method

The mutate method extends SWR's mutate function:


setSize Method

Allows updating the number of pages to load.


Usage Example

import useSWRInfinite from 'path-to/useSWRInfinite'

function MyComponent() {
  const { data, error, size, setSize, mutate, isValidating } = useSWRInfinite(
    (index, previousPageData) => {
      // Stop fetching if no more data
      if (previousPageData && !previousPageData.length) return null
      return `/api/items?page=${index + 1}`
    },
    fetcher,
    {
      initialSize: 3,
      revalidateAll: false,
      parallel: true
    }
  )

  if (error) return <div>Error loading data</div>
  if (!data) return <div>Loading...</div>

  // Flatten loaded pages
  const items = data.flat()

  return (
    <>
      <ul>
        {items.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
      <button onClick={() => setSize(size + 1)}>Load More</button>
    </>
  )
}

Important Implementation Details


Interactions with Other Parts of the System


Mermaid Class Diagram

classDiagram
    class InfiniteMiddleware {
        - didMountRef: Ref<boolean>
        - infiniteKey: string | undefined
        - lastPageSizeRef: Ref<number>
        - get: Function
        - set: Function
        - subscribeCache: Function
        - resolvePageSize(): number
        + useSWRNext(getKey, fetcher, config): SWRResponse<Data[]>
        + mutate(data?, opts?): Promise<Data[]>
        + setSize(size | (size) => size): Promise<Data[]>
        + data: Data[]
        + error: Error | undefined
        + isValidating: boolean
        + isLoading: boolean
        + size: number
    }

    class useSWRInfinite {
        + (getKey, fetcher, config): {
            size: number
            setSize: Function
            mutate: Function
            data: Data[]
            error: Error | undefined
            isValidating: boolean
            isLoading: boolean
          }
    }

    useSWRInfinite --|> InfiniteMiddleware

Summary

The index.ts file implements the infinite loading middleware for SWR, enabling React developers to easily fetch, cache, and manage paginated or infinite scroll data. It extends the core SWR hook into a powerful useSWRInfinite hook with advanced features like dynamic page keys, configurable revalidation, parallel fetching, and cache-backed page size state.

This modular and extensible design integrates deeply with SWR’s global cache and middleware architecture, providing robust infinite loading capabilities while maintaining a simple, declarative API surface.


End of Documentation for index.ts