Skip to content

Conversation

@panteliselef
Copy link
Member

@panteliselef panteliselef commented Nov 11, 2025

Description

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features

    • Added support for keepPreviousData in subscription and pagination hooks so previous results can persist during refetches.
  • Tests

    • Added tests verifying behavior when keepPreviousData is enabled (retains data) and disabled (clears data) during refetches.
  • Documentation

    • Added changelog entry describing this patch release.

@changeset-bot
Copy link

changeset-bot bot commented Nov 11, 2025

🦋 Changeset detected

Latest commit: 85a1cb5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@clerk/shared Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/chrome-extension Patch
@clerk/clerk-js Patch
@clerk/elements Patch
@clerk/expo-passkeys Patch
@clerk/clerk-expo Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/clerk-react Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/themes Patch
@clerk/types Patch
@clerk/vue Patch
@clerk/localizations Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Nov 11, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Nov 13, 2025 11:27am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds internal KeepPreviousDataFn and wiring so keepPreviousData affects React Query placeholderData in useSubscription and usePagesOrInfinite; adjusts pagination options passing and adds tests validating keepPreviousData true/false behavior. Also adds a changelog entry.

Changes

Cohort / File(s) Summary
Changelog Entry
/.changeset/soft-beers-sit.md
Adds a changelog entry describing a patch release that enables keepPreviousData behavior in the internal React Query variant of useSubscription.
Tests
packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
Adds two tests using a deferred promise to verify: (1) data is retained during refetch when keepPreviousData=true; (2) data is cleared during refetch when keepPreviousData=false.
Hook logic — usePagesOrInfinite
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
Introduces an internal KeepPreviousDataFn<Data>(previousData: Data): Data and uses it as placeholderData when keepPreviousData is enabled.
Hook logic — useSubscription
packages/shared/src/react/hooks/useSubscription.rq.tsx
Adds the same internal KeepPreviousDataFn, reads params?.keepPreviousData into keepPreviousData, and sets placeholderData to the helper when enabled and queries are active.
Pagination config
packages/shared/src/react/hooks/createBillingPaginatedHook.tsx
Changes how pagination options are passed to usePagesOrInfinite by spreading a wrapped object containing keepPreviousData and infinite and casting to PaginatedHookConfig<unknown> (typing adjustment, no behavior change).

Sequence Diagram(s)

sequenceDiagram
  participant Consumer as Hook Consumer
  participant Hook as useSubscription / usePagesOrInfinite
  participant RQ as ReactQuery

  Note over Hook,RQ: New internal helper KeepPreviousDataFn exists\nand is used as placeholderData when enabled
  Consumer->>Hook: mount / trigger refetch (params.keepPreviousData = true|false)
  Hook->>RQ: request data (config includes placeholderData = KeepPreviousDataFn or undefined)
  alt keepPreviousData = true (queries enabled)
    RQ-->>Consumer: returns previous data immediately (isFetching=true)
    RQ->>Hook: final data arrives later (isFetching=false/isLoading=false)
    Hook-->>Consumer: updates with new data
  else keepPreviousData = false
    RQ-->>Consumer: placeholder is undefined (isLoading=true)
    RQ->>Hook: final data arrives later
    Hook-->>Consumer: updates with new data
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas requiring extra attention:
    • usePagesOrInfinite.rq.tsx and useSubscription.rq.tsx — ensure placeholderData integration preserves previous behavior and typing.
    • createBillingPaginatedHook.tsx — confirm the cast to PaginatedHookConfig<unknown> doesn't lose important type information.
    • New tests — validate reliability of deferred promise usage and timing assumptions.

Poem

🐇 I nibble code where queries play,

Previous crumbs I keep at bay,
When fetching runs, old carrots stay—
Then fresh sweet data hops my way. ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: adding support for keepPreviousData in useSubscription.rq, which is clearly reflected in the code changes to useSubscription.rq.tsx and related files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elef/add-support-for-keep-previous-data-in-rq

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ad91c39 and 85a1cb5.

📒 Files selected for processing (1)
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/shared/src/react/hooks/tests/useSubscription.spec.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)

Comment @coderabbitai help to get the list of available commands and usage tips.

@panteliselef panteliselef self-assigned this Nov 13, 2025
# Conflicts:
#	packages/clerk-js/src/ui/contexts/components/Plans.tsx
#	packages/shared/src/react/hooks/useSubscription.rq.tsx
@panteliselef panteliselef changed the title Elef/add support for keep previous data in rq feat(shared): Support for keepPreviousData in useSubscription.rq Nov 13, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)

14-19: Duplicate helper function identified.

This KeepPreviousDataFn is identical to the one in useSubscription.rq.tsx. See the review comment on useSubscription.rq.tsx (lines 17-22) for the refactoring suggestion to extract this to a shared utility.

🧹 Nitpick comments (1)
packages/shared/src/react/hooks/useSubscription.rq.tsx (1)

17-22: Consider extracting KeepPreviousDataFn to a shared utility.

This function is duplicated identically in usePagesOrInfinite.rq.tsx (lines 14-19). Extract it to a shared location to follow DRY principles and simplify maintenance.

Consider creating a shared utility file:

// packages/shared/src/react/utils/reactQueryHelpers.ts
/**
 * @internal
 */
export function KeepPreviousDataFn<Data>(previousData: Data): Data {
  return previousData;
}

Then import it in both files:

+import { KeepPreviousDataFn } from '../utils/reactQueryHelpers';
+
-/**
- * @internal
- */
-function KeepPreviousDataFn<Data>(previousData: Data): Data {
-  return previousData;
-}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c63cc8e and ad91c39.

📒 Files selected for processing (5)
  • .changeset/soft-beers-sit.md (1 hunks)
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (2 hunks)
  • packages/shared/src/react/hooks/createBillingPaginatedHook.tsx (1 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (2 hunks)
  • packages/shared/src/react/hooks/useSubscription.rq.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/shared/src/react/hooks/createBillingPaginatedHook.tsx (1)
packages/shared/src/react/types.ts (1)
  • PaginatedHookConfig (89-102)
packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (4)
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (1)
  • createMockOrganization (61-63)
packages/shared/src/react/hooks/useSubscription.rq.tsx (1)
  • useSubscription (30-84)
packages/shared/src/react/hooks/useSubscription.swr.tsx (1)
  • useSubscription (22-71)
packages/shared/src/utils/createDeferredPromise.ts (1)
  • createDeferredPromise (11-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (8)
packages/shared/src/react/hooks/useSubscription.rq.tsx (2)

46-46: LGTM!

The extraction of keepPreviousData with a sensible default is clean and consistent with the codebase patterns.


70-70: LGTM!

The conditional logic correctly applies placeholderData only when both keepPreviousData is enabled and queries are active, preventing stale data retention when queries are disabled.

.changeset/soft-beers-sit.md (1)

1-5: LGTM!

The changelog entry clearly documents the new keepPreviousData feature and is correctly scoped as a patch-level change.

packages/shared/src/react/hooks/createBillingPaginatedHook.tsx (1)

108-111: Verify the necessity of the type cast.

The wrapping and casting to PaginatedHookConfig<unknown> suggests a type compatibility issue. While this should work at runtime, the unknown type parameter may be masking a type error or indicate that the generic type flow could be improved.

Consider investigating whether the type parameter can be more specific or if the wrapping/spreading pattern can be simplified:

// Current approach
...({
  keepPreviousData: safeValues.keepPreviousData,
  infinite: safeValues.infinite,
} as PaginatedHookConfig<unknown>),

// Alternative if types align properly
keepPreviousData: safeValues.keepPreviousData,
infinite: safeValues.infinite,

If the cast is necessary due to type system limitations, consider adding a comment explaining why.

packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)

75-75: LGTM!

The conditional placeholderData configuration correctly preserves previous data during pagination when keepPreviousData is enabled.

packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (3)

4-4: LGTM!

The import of createDeferredPromise enables precise control over async timing in the new tests.


149-177: LGTM! Excellent test coverage.

This test thoroughly validates the keepPreviousData=true behavior:

  • Verifies previous data is retained during refetch (isFetching=true, isLoading=false)
  • Confirms data updates after the deferred promise resolves
  • Validates the correct number of fetcher invocations

The use of createDeferredPromise to control async timing is a solid testing pattern.


179-209: LGTM! Comprehensive test coverage.

This test effectively validates the keepPreviousData=false behavior:

  • Confirms data is cleared during refetch (isFetching=true, isLoading=true, data=undefined)
  • Verifies data populates after resolution
  • Validates correct fetcher call count

The test properly exercises the distinction between isLoading and isFetching states, which is important for React Query semantics.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 13, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7203

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7203

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7203

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7203

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7203

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7203

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@7203

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@7203

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7203

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7203

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7203

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7203

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7203

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7203

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@7203

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7203

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@7203

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7203

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7203

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7203

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@7203

@clerk/types

npm i https://pkg.pr.new/@clerk/types@7203

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7203

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7203

commit: 85a1cb5

@panteliselef panteliselef merged commit 42f0d95 into main Nov 13, 2025
71 of 77 checks passed
@panteliselef panteliselef deleted the elef/add-support-for-keep-previous-data-in-rq branch November 13, 2025 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants