Skip to content

Conversation

DamianOsipiuk
Copy link
Contributor

@DamianOsipiuk DamianOsipiuk commented Oct 10, 2025

🎯 Changes

Fixes: #9667, #9683

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features

    • Added refetchOnRestore option (true | false | 'always') to control refetching when persisted queries are restored.
  • Documentation

    • Updated React and Vue persister docs to document refetchOnRestore, new persister utilities (persist/retrieve/restore/gc), and that setQueryData changes are not persisted.
    • Expanded storage docs to allow typed values, optional entries enumeration, and sync/async implementations.
  • Tests

    • Added tests covering refetch behavior for all refetchOnRestore modes.
  • Chores

    • Added changeset documenting the minor release.

Copy link

changeset-bot bot commented Oct 10, 2025

🦋 Changeset detected

Latest commit: a462859

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

This PR includes changesets to release 7 packages
Name Type
@tanstack/query-persist-client-core Minor
@tanstack/angular-query-persist-client Patch
@tanstack/query-async-storage-persister Patch
@tanstack/query-sync-storage-persister Patch
@tanstack/react-query-persist-client Patch
@tanstack/solid-query-persist-client Patch
@tanstack/svelte-query-persist-client 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

@github-actions github-actions bot added documentation Improvements or additions to documentation package: query-persist-client-core labels Oct 10, 2025
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Walkthrough

Adds a new StoragePersisterOptions.refetchOnRestore (boolean | 'always'), defaults it to true, updates restoration logic to conditionally trigger query.fetch(), adds tests covering the behaviors, and updates React/Vue docs and Vue AsyncStorage signatures.

Changes

Cohort / File(s) Summary
Core persister logic
packages/query-persist-client-core/src/createPersister.ts
Adds `StoragePersisterOptions.refetchOnRestore?: boolean
Tests
packages/query-persist-client-core/src/__tests__/createPersister.test.ts
Adds tests verifying restore + refetch when refetchOnRestore='always' and no refetch when refetchOnRestore=false; follows existing test patterns.
Docs — React
docs/framework/react/plugins/createPersister.md
Documents new `refetchOnRestore?: boolean
Docs — Vue & storage interface
docs/framework/vue/plugins/createPersister.md
Documents refetchOnRestore with default true; makes AsyncStorage<TStorageValue = string> generic, method signatures return MaybePromise, and adds optional entries?: () => MaybePromise<Array<[key: string, value: TStorageValue]>>. Adds persister utilities and usage notes.
Changeset
.changeset/pretty-geese-scream.md
Adds a changeset entry noting the new refetchOnRestore setting (minor version bump).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant Persister
  participant Storage
  participant QueryCache
  participant Query
  participant Network

  App->>Persister: init(refetchOnRestore)
  Persister->>Storage: read persisted state
  Storage-->>Persister: persisted queries
  Persister->>QueryCache: restore queries
  alt refetchOnRestore == 'always'
    Note right of Persister: Always trigger fetch
    Persister->>Query: fetch()
    Query->>Network: request
    Network-->>Query: response
  else refetchOnRestore == true
    Note right of Persister: Fetch only if stale
    Persister->>Query: isStale?
    alt stale
      Persister->>Query: fetch()
      Query->>Network: request
      Network-->>Query: response
    else fresh
      Note right of Query: No fetch
    end
  else refetchOnRestore == false
    Note right of Query: No fetch on restore
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibble docs and hop through tests,
A flag decides if fetching rests.
'Always', true, or false — I choose,
Carrots saved and queries snooze.
Hooray for persisters — rabbit-approved zest! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ⚠️ Warning The PR description fails to provide a summary of the actual changes or their motivation in the “🎯 Changes” section, instead only linking to issues, so it does not fulfill the template requirement to describe what was changed and why. Please expand the “🎯 Changes” section to include a concise description of the code modifications introduced and the reasoning behind them, ensuring it aligns with the repository’s PR description template.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely summarizes the primary change by indicating that the createQueryPersister now accepts an option to modify refetch behavior after restoration, and it follows conventional commit formatting with a clear scope and action.
✨ 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 do/persister-add-refetch-control

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

nx-cloud bot commented Oct 10, 2025

View your CI Pipeline Execution ↗ for commit a462859

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 45s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 45s View ↗

☁️ Nx Cloud last updated this comment at 2025-10-10 20:59:54 UTC

Copy link

pkg-pr-new bot commented Oct 10, 2025

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@9745

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@9745

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@9745

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@9745

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@9745

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@9745

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@9745

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@9745

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@9745

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@9745

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@9745

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@9745

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@9745

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@9745

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@9745

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@9745

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@9745

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@9745

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@9745

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@9745

commit: a462859

Copy link
Contributor

github-actions bot commented Oct 10, 2025

Sizes for commit a462859:

Branch Bundle Size
Main
This PR

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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4a0cd5 and e6ce6e6.

📒 Files selected for processing (4)
  • docs/framework/react/plugins/createPersister.md (2 hunks)
  • docs/framework/vue/plugins/createPersister.md (4 hunks)
  • packages/query-persist-client-core/src/__tests__/createPersister.test.ts (1 hunks)
  • packages/query-persist-client-core/src/createPersister.ts (3 hunks)
⏰ 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). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (8)
docs/framework/react/plugins/createPersister.md (1)

172-178: Documentation is clear and accurate.

The documentation effectively describes the three behavioral modes of refetchOnRestore and their effects on query restoration.

packages/query-persist-client-core/src/createPersister.ts (3)

65-71: JSDoc is clear and accurate.

The documentation properly describes all three modes of operation and specifies the default value.


106-106: Default value is correctly set.

The default of true aligns with the documented behavior and provides sensible out-of-the-box refetch semantics.


215-220: Implementation correctly handles all refetch modes.

The conditional logic properly implements the three behaviors:

  • 'always': refetches unconditionally
  • true: refetches only when stale
  • false: never refetches
docs/framework/vue/plugins/createPersister.md (4)

36-36: Generic reference is appropriate for Vue documentation.

Removing the React Native-specific reference makes the documentation more framework-agnostic and suitable for Vue users.


40-40: GitHub issue reference adds helpful context.

Linking to the issue provides users with additional context about the limitation with setQueryData() operations.


69-124: Utilities documentation improves completeness.

Adding the "Additional utilities" section brings the Vue documentation to parity with the React documentation and provides essential information about helper functions.


169-175: Documentation accurately reflects the implementation.

The refetchOnRestore option is properly documented with all three modes, and the AsyncStorage interface is correctly shown as generic with optional entries() support, matching the TypeScript implementation.

Also applies to: 182-186, 198-198

Comment on lines 263 to 289
test('should restore item from the storage and refetch when `refetchOnRestore` is set to `always`', async () => {
const storage = getFreshStorage()
const { context, persister, query, queryFn, storageKey } = setupPersister(
['foo'],
{
storage,
},
)

await storage.setItem(
storageKey,
JSON.stringify({
buster: '',
state: { dataUpdatedAt: Date.now() + 1000, data: '' },
}),
)

await persister.persisterFn(queryFn, context, query)
query.state.isInvalidated = true
query.fetch = vi.fn()

await vi.advanceTimersByTimeAsync(0)

expect(queryFn).toHaveBeenCalledTimes(0)
expect(query.fetch).toHaveBeenCalledTimes(1)
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Tests are not passing the refetchOnRestore option.

The test claims to verify behavior when refetchOnRestore is set to 'always', but the persister is created without passing this option. The test should include refetchOnRestore: 'always' in the options object passed to setupPersister:

Apply this diff to fix the test:

   test('should restore item from the storage and refetch when `refetchOnRestore` is set to `always`', async () => {
     const storage = getFreshStorage()
     const { context, persister, query, queryFn, storageKey } = setupPersister(
       ['foo'],
       {
         storage,
+        refetchOnRestore: 'always',
       },
     )

Additionally, to properly test that 'always' refetches even when data is NOT stale, consider removing the query.state.isInvalidated = true line (Line 281), since the future dataUpdatedAt already ensures the query appears fresh, and 'always' should refetch regardless of staleness.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('should restore item from the storage and refetch when `refetchOnRestore` is set to `always`', async () => {
const storage = getFreshStorage()
const { context, persister, query, queryFn, storageKey } = setupPersister(
['foo'],
{
storage,
},
)
await storage.setItem(
storageKey,
JSON.stringify({
buster: '',
state: { dataUpdatedAt: Date.now() + 1000, data: '' },
}),
)
await persister.persisterFn(queryFn, context, query)
query.state.isInvalidated = true
query.fetch = vi.fn()
await vi.advanceTimersByTimeAsync(0)
expect(queryFn).toHaveBeenCalledTimes(0)
expect(query.fetch).toHaveBeenCalledTimes(1)
})
test('should restore item from the storage and refetch when `refetchOnRestore` is set to `always`', async () => {
const storage = getFreshStorage()
const { context, persister, query, queryFn, storageKey } = setupPersister(
['foo'],
{
storage,
refetchOnRestore: 'always',
},
)
await storage.setItem(
storageKey,
JSON.stringify({
buster: '',
state: { dataUpdatedAt: Date.now() + 1000, data: '' },
}),
)
await persister.persisterFn(queryFn, context, query)
query.state.isInvalidated = true
query.fetch = vi.fn()
await vi.advanceTimersByTimeAsync(0)
expect(queryFn).toHaveBeenCalledTimes(0)
expect(query.fetch).toHaveBeenCalledTimes(1)
})
🤖 Prompt for AI Agents
In packages/query-persist-client-core/src/__tests__/createPersister.test.ts
around lines 263 to 288, the test claims to verify refetchOnRestore: 'always'
but does not pass that option and also manually marks the query as invalidated;
update the setupPersister call to include refetchOnRestore: 'always' in the
options object and remove the line that sets query.state.isInvalidated = true so
the test verifies that 'always' triggers a refetch even when the restored data
is fresh.

@DamianOsipiuk DamianOsipiuk force-pushed the do/persister-add-refetch-control branch from e6ce6e6 to a462859 Compare October 10, 2025 20:55
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.88%. Comparing base (f4a0cd5) to head (a462859).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #9745       +/-   ##
===========================================
+ Coverage   45.51%   80.88%   +35.36%     
===========================================
  Files         196       36      -160     
  Lines        8324      659     -7665     
  Branches     1902      186     -1716     
===========================================
- Hits         3789      533     -3256     
+ Misses       4093      109     -3984     
+ Partials      442       17      -425     
Components Coverage Δ
@tanstack/angular-query-experimental ∅ <ø> (∅)
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister 43.85% <ø> (ø)
@tanstack/query-broadcast-client-experimental ∅ <ø> (∅)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core ∅ <ø> (∅)
@tanstack/query-devtools ∅ <ø> (∅)
@tanstack/query-persist-client-core 80.00% <100.00%> (+0.39%) ⬆️
@tanstack/query-sync-storage-persister 84.61% <ø> (ø)
@tanstack/query-test-utils ∅ <ø> (∅)
@tanstack/react-query 96.01% <ø> (ø)
@tanstack/react-query-devtools 10.00% <ø> (ø)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client 100.00% <ø> (ø)
@tanstack/solid-query ∅ <ø> (∅)
@tanstack/solid-query-devtools ∅ <ø> (∅)
@tanstack/solid-query-persist-client 100.00% <ø> (ø)
@tanstack/svelte-query ∅ <ø> (∅)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client ∅ <ø> (∅)
@tanstack/vue-query ∅ <ø> (∅)
@tanstack/vue-query-devtools ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@DamianOsipiuk DamianOsipiuk merged commit 5cd86c6 into main Oct 10, 2025
9 checks passed
@DamianOsipiuk DamianOsipiuk deleted the do/persister-add-refetch-control branch October 10, 2025 21:04
@github-actions github-actions bot mentioned this pull request Oct 10, 2025
Hellol77 pushed a commit to Hellol77/query that referenced this pull request Oct 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: query-persist-client-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refetchOnMount and queryClient.invalidateQueries() do not work as expected when using experimental_createQueryPersister

1 participant