-
-
Notifications
You must be signed in to change notification settings - Fork 516
Fix useSWRInfinite pagination and header support (v7) #2586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix useSWRInfinite pagination and header support (v7) #2586
Conversation
…rom key Previously, the generated swrFn for useSWRInfinite did not accept any parameters from the key loader, causing pagination parameters to be inaccessible. This fix: - Separates path parameters (fixed) from query parameters (variable) - Generates swrFn with (_url, pageParams) signature for infinite hooks - Passes path params and page params separately to the operation function This enables proper pagination support in useSWRInfinite hooks.
Previously, pageParams had 'any' type in the generated swrFn for useSWRInfinite hooks. This change extracts the query parameter type from the GetterProp definition and uses it as the type annotation. Before: const swrFn = (_url: string, pageParams: any) => listPets(pageParams, options) After: const swrFn = (_url: string, pageParams: ListPetsParams) => listPets(pageParams, options) The fallback type is 'never' instead of 'any', which provides better type safety by causing compilation errors if query params are missing when expected. This improves type safety and enables better IDE autocomplete for pagination parameters.
The original implementation wrapped the keyLoader in an arrow function: () => isEnabled ? getKeyLoader() : null This is incorrect because SWR calls swrKeyLoader with (pageIndex, previousPageData) arguments, but the wrapper ignores them. Fixed to return the actual keyLoader function directly when enabled: isEnabled ? getKeyLoader() : () => null This allows SWR to properly pass pageIndex and previousPageData to the key loader function.
Changed previousPageData from required to optional parameter in useSWRInfinite keyLoader. This allows users to call keyLoader(0) without explicitly passing undefined for the first page, which is more ergonomic and complies with ESLint rules (unicorn/no-useless-undefined).
Fixed regression where headers were dropped in useSWRInfinite hooks. The swrFn now correctly passes headers between pageParams and options: - With query params: operationName(pathParams, pageParams, headers, options) - Without query params: operationName(pathParams, headers, options) Changes: - Extract headerOnlyParams from props (filter by GetterPropType.HEADER) - Pass headerOnlyParams to generateSwrImplementation - Include headers in swrFn generation between pageParams and options Note: This fix only applies to infinite hooks. A separate pre-existing bug with mutation fetchers dropping headers remains to be addressed.
Add tests to verify type safety and proper parameter handling in useSWRInfinite: - Unit tests for query parameter type extraction (client.test.ts) - Regression tests for page: number type in pageParams - Tests for headers in both infinite and regular hooks - Test configuration with headers enabled (petstoreWithHeaders) Tests verify: - pageParams includes page: number type - Headers are passed between pageParams and options - Type safety without using 'as any' or type assertions - Optional previousPageData parameter - Query parameter type extraction logic
This fixes a bug where mutation fetchers and hooks were dropping header parameters when headers: true was enabled in the config. Changes: - Add GetterPropType.HEADER to swrProps filter for mutation hooks - Add GetterPropType.HEADER to swrMutationFetcherProperties - Generate proper parameter lists for GET and POST/PUT/DELETE mutations - Maintain correct parameter order: (params, headers, options) Also adds comprehensive regression tests for: - Mutation hooks with headers (useCreatePets) - Mutation fetchers with headers (getCreatePetsMutationFetcher) - Both headers: true and headers: false configurations
SWR passes the key array as a single argument to the fetcher, not as spread arguments. The fetcher must destructure the array to access individual elements. Before (causes runtime error): const swrFn = (_url: string, pageParams: Type) => ... // _url receives the entire array, pageParams is undefined After (correct): const swrFn = ([_url, pageParams]: [string, Type]) => ... // Properly destructures the array from SWR
Verifies that the key loader returns a properly typed tuple and that TypeScript compilation succeeds with the array destructuring pattern in swrFn.
|
I was unsure whether to target the master branch or the v7 branch. That said, this is just my preference, so I would like to defer the final decision to you. Currently this PR is based on v7, but please let me know if it should instead be based on master. |
|
Can you submit the PR against both v7 and V8 please. |
|
@melloware I've created PR #2587 for the master branch. |
|
I will push a 7.17.0 with these changes |
|
Thanks for the quick turnaround! |
|
ok 7.17.0 is on NPM if you want to give it a shot. |
Problem
The SWR code generator has several type safety and parameter handling issues:
Missing Pagination Support:
useSWRInfiniteimplementation doesn't support pagination parameters:swrFndoesn't accept parameters from the key loaderFunction Wrapping Bug:
swrKeyLoaderis incorrectly wrapped in an arrow function:(pageIndex, previousPageData)argumentsMissing Headers in useSWRInfinite: When
headers: trueis enabled, headers are not passed to theswrFn:Missing Headers in Mutation Fetchers: Mutation hooks and fetchers don't include header parameters:
useXXXMutationhooks don't accept headersSolution
This PR fixes all issues:
swrFnthat acceptspageParamsfrom the key loader with proper type annotation extracted fromGetterPropswrKeyLoaderto allow SWR to pass pagination arguments correctlyswrFnbetweenpageParamsand optionsBefore
After
Changes
1. Fix useSWRInfinite swrFn parameter handling
swrFnthat accepts([_url, pageParams])from the key loaderoperationName(pathParams, pageParams, options)2. Add type annotation to pageParams
GetterProp.definition(e.g.,"params: ListPetsParams"→"ListPetsParams")neveras fallback type for better type safety (causes compilation errors if params are missing when expected)3. Fix swrKeyLoader function wrapping bug
() => isEnabled ? getKeyLoader() : null(pageIndex, previousPageData)arguments to the key loaderisEnabled ? getKeyLoader() : () => null4. Fix headers in useSWRInfinite
swrFngeneration betweenpageParamsandhttpRequestSecondArgoperationName(pageParams, headers, options)5. Fix headers in mutation fetchers and hooks
GetterPropType.HEADERinswrPropsfilter for mutation hooksswrMutationFetcherPropertiesfor fetcher function parameters(params, headers, options)for fetcher signatures6. Add comprehensive tests
headers: trueto catch header-related bugsTesting
All tests pass successfully:
Affected Files
packages/swr/src/index.ts- Core implementation (pagination, headers, mutations)packages/swr/src/client.test.ts- Unit tests for type extractionpackages/swr/src/index.test.ts- Unit tests for builderpackages/swr/vitest.config.ts- Test configurationpackages/swr/package.json- Added test script and vitest dependencytests/regressions/swr.ts- Regression tests for type safety and headerstests/configs/swr.config.ts- AddedpetstoreWithHeaderstest configurationBreaking Changes
None. This PR fixes bugs and adds support for features that were previously non-functional:
useSWRInfinitepagination was broken and unusableheaders: truewas configuredAfter regeneration, previously broken functionality will now work correctly.
Related Issues
Fixes #2106