Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[v4] Fix infinite re-renders with synchronous queries in suspense mode #9584

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

Open
joseph0926 wants to merge 5 commits into TanStack:v4
base: v4
Choose a base branch
Loading
from joseph0926:fix/suspense-sync-query-cachetime-v4

Conversation

Copy link
Contributor

@joseph0926 joseph0926 commented Aug 21, 2025
edited
Loading

fixes: #9583
comment: #9583 (comment)

Problem

After comparing the suspension-related codes, the two biggest differences between v5 and v4 are as follows.

In suspense.ts,
ensureStaleTime (renamed to ensureSuspenseTimers in v5) in v4 only includes a guard for staleTime, while in v5 it includes guards for both staleTime and gcTime.

Another difference is that in v4, shouldSuspend determines suspension using willFetch(result, isRestoring), whereas in v5 it relies on result.isPending. However, since v4 does not handle isPending (more specifically, it does not handle thenables),

I'm not sure if this is intentional, but in v5, when in suspense mode, ensureSuspenseTimers seems to set the minimum gcTime to 1000 (even if you explicitly set it to less than 1000).
Therefore, perhaps, the simplest solution without major structural changes is to add a guard for cacheTime to ensureStaleTime.

Solution

This PR adds a guard for cacheTime in the ensureStaleTime function to match v5's behavior. When suspense mode is enabled, the function now ensures a minimum cacheTime of 1000ms, preventing the cache from being deleted before React's rendering cycle completes.

The fix specifically addresses the scenario where synchronous query functions with suspense: true and cacheTime < 2ms cause infinite re-render loops. By enforcing a minimum cacheTime, we ensure that

  • The query result remains cached long enough for React to complete its suspense boundary resolution
  • Synchronous queries behave consistently with asynchronous queries in suspense mode
  • The behavior aligns with v5's implementation, making future migrations smoother

Testing

Added comprehensive test cases to verify

  • Boundary value handling (cacheTime values from 0 to 2000ms)
  • User-specified cacheTime values are preserved when >= 1000ms
  • Both synchronous and asynchronous queries work correctly with the adjustment
  • The relationship between staleTime and cacheTime is maintained
  • The infinite re-render loop with synchronous queries and cacheTime: 0 is resolved

suhdonghwi and manudeli reacted with heart emoji
Copy link

coderabbitai bot commented Aug 21, 2025
edited
Loading

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

nx-cloud bot commented Aug 21, 2025
edited
Loading

View your CI Pipeline Execution ↗ for commit 84f568a

Command Status Duration Result
nx affected --targets=test:lib,test:types,test:... ⛔ Cancelled 3h 3m 39s View ↗

☁️ Nx Cloud last updated this comment at 2025年09月01日 15:07:06 UTC

Copy link

codesandbox-ci bot commented Aug 21, 2025
edited
Loading

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 84f568a:

Sandbox Source
@tanstack/query-example-react-basic-typescript Configuration
@tanstack/query-example-solid-basic-typescript Configuration
@tanstack/query-example-svelte-basic Configuration
@tanstack/query-example-vue-basic Configuration

Copy link
Contributor Author

joseph0926 commented Aug 21, 2025
edited
Loading

(削除) The v4 quarterly CI is currently delayed due to an issue (taking over an hour and failing due to an Nx Cloud error).
This issue appears to be similar in other v4 PRs (https://github.com/TanStack/query/actions/runs/16601605388/job/46962541804?pr=9334) as well as this PR. Local tests pass successfully.
Therefore, I will switch to Draft for now. (削除ここまで)

@joseph0926 joseph0926 marked this pull request as draft August 21, 2025 03:07
@joseph0926 joseph0926 marked this pull request as ready for review August 24, 2025 09:53
Copy link
Collaborator

TkDodo commented Sep 1, 2025

not sure why CI hangs here but I really don’t want to spend time backporting something to a 1+ year old code-base that has already been fixed in v5.

@manudeli if you want to investigate why this hangs, please do. Otherwise, let’s close this PR.

joseph0926 reacted with thumbs up emoji

@manudeli manudeli self-requested a review September 1, 2025 11:37
Copy link
Collaborator

manudeli commented Sep 1, 2025

not sure why CI hangs here but I really don’t want to spend time backporting something to a 1+ year old code-base that has already been fixed in v5.

@manudeli if you want to investigate why this hangs, please do. Otherwise, let’s close this PR.

Totally understand not wanting to spend time backporting to the old v4 branch — thanks a lot for all the work you’ve already done there.

For now, @lachlancollins kindly offered in Discord to take a look at the CI issue, so I’ll wait for that. As for v4 backports, I think we’ll only need to cover a few essentials:

  1. infiniteQueryOptions, suspense hook
  2. Fix for infinite re-render in Suspense mode
  3. React 19 compatibility

Beyond these, I don’t expect further backports will be necessary. I’ll make sure to take care of these on my side, so you don’t need to worry about v4 anymore.

joseph0926 reacted with thumbs up emoji

@manudeli manudeli self-assigned this Sep 1, 2025
Copy link
Contributor Author

joseph0926 commented Sep 1, 2025
edited
Loading

84f568a

Hello @manudeli ,

I had removed the most critical test for this issue because I believed it was causing an Nx CI problem.
However, since it has been confirmed that this test does not cause CI issues, I will add it back.

 it('should not cause infinite re-renders with synchronous query function and cacheTime: 0', async () => {
 const key = queryKey()
 let renderCount = 0
 let queryFnCallCount = 0
 const maxChecks = 20
 function Page() {
 renderCount++
 if (renderCount > maxChecks) {
 throw new Error(`Infinite loop detected! Renders: ${renderCount}`)
 }
 const result = useQuery(
 key,
 () => {
 queryFnCallCount++
 return 42
 },
 {
 cacheTime: 0,
 suspense: true,
 },
 )
 return <div>data: {result.data}</div>
 }
 const rendered = renderWithClient(
 queryClient,
 <React.Suspense fallback="loading">
 <Page />
 </React.Suspense>,
 )
 await waitFor(() => rendered.getByText('data: 42'))
 expect(renderCount).toBeLessThan(5)
 expect(queryFnCallCount).toBe(1)
 expect(rendered.queryByText('data: 42')).not.toBeNull()
 expect(rendered.queryByText('loading')).toBeNull()
 })
manudeli reacted with thumbs up emoji

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Reviewers

@manudeli manudeli Awaiting requested review from manudeli

Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /