Skip to content

SWR: useSWRInfinite pagination termination logic doesn't handle various response types #2584

@tk1024

Description

@tk1024

Problem

The generated useSWRInfinite key loader's pagination termination logic only checks for the .data property, which causes TypeScript errors and incorrect behavior for various API response types.

Current implementation:

  export const getListPetsInfiniteKeyLoader = (params: ListPetsParams) => {
    return (page: number, previousPageData: Awaited<ReturnType<typeof listPets>>) => {
      if (previousPageData && !previousPageData.data) return null

      return [`/pets`, ...(params ? [{...params,page}]: [{page}])] as const;
    }
  }

Issues

  1. TypeScript errors when response type doesn't have a .data property
  2. Doesn't handle direct array responses (e.g., Pet[]):
  • Pagination never terminates because arrays don't have a .data property
  1. Doesn't handle single object responses (e.g., Pet):
  • Pagination never terminates because objects don't have a .data property

Expected Behavior

The pagination termination logic should handle three common response patterns:

  1. Direct array response (e.g., Pet[])
  • Stop pagination when array is empty: !previousPageData.length
  1. Wrapped response with data array (e.g., { data: Pet[], status: 200 })
  • Stop pagination when data array is empty: !previousPageData.data.length
  1. Single object response (e.g., Pet, QueuedTask)
  • Stop pagination after first page (non-paginated endpoint)

Proposed Solution

  export const getListPetsInfiniteKeyLoader = (params: ListPetsParams) => {
    return (page: number, previousPageData: Awaited<ReturnType<typeof listPets>>) => {
      if (previousPageData) {
        const isArrayResponse = Array.isArray(previousPageData)
        const hasDataProperty = "data" in previousPageData

        // Case 1: Direct array response (e.g., Pet[])
        // Stop pagination when array is empty
        if (isArrayResponse && !previousPageData.length) return null

        // Case 2: Wrapped response with data array (e.g., { data: Pet[], status: 200 })
        // Stop pagination when data array is empty
        if (hasDataProperty && Array.isArray(previousPageData.data) && !previousPageData.data.length) return null

        // Case 3: Single object response (e.g., Pet)
        // Stop pagination after first page
        if (!isArrayResponse && !hasDataProperty) return null
      }

      return [`/pets`, ...(params ? [{...params,page}]: [{page}])] as const;
    }
  }

Environment

  • Orval version: 8.0.0-rc.2
  • TypeScript: Latest
  • SWR: Latest

Metadata

Metadata

Assignees

Labels

swrSWR related issues

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions