Skip to content

isFetchedAfterMount was broken in commit 1c8a921 / v5.87.1 #9656

@0xdiid

Description

@0xdiid

Describe the bug

Hello!

It appears that isFetchedAfterMount was broken in 5.87.1 through that change inadvertently updating the dataUpdateCount. We're seeing behavior where the isLoading flag is set to false when data is loaded from cache, but since isFetchedAfterMount is inadvertently set to true too early we can't tell if that data was loaded from the server or from the cache. In essence, I believe that in cases where you are persisting data the isFetchedAfterMount flag might be entirely broken.

From Claude's analysis:

Root Cause Analysis

The commit 1c8a92167769f322d0206325b98493769afb0961 introduced logic that updates initialData when a Query exists without data. The issue is that when setData is called with manual: true, it increments dataUpdateCount from 0 to 1, even though this data wasn't actually fetched from the server but just set as initial data.

The Problem Flow:

  1. Prefetch scenario: A query is created via prefetching (data is undefined, status is pending)
  2. Observer mounts with initialData: When an observer mounts with initialData set
  3. setOptions is called: The new code in query.ts:210-218 detects the query has no data and sets the initialData
  4. setData with manual:true: This calls setData with manual: true, which increments dataUpdateCount from 0 to 1
  5. queryInitialState capture: The observer captures the query state as #currentQueryInitialState with dataUpdateCount: 1
  6. isFetchedAfterMount calculation: When calculated, it compares current dataUpdateCount (1) with initial dataUpdateCount (1), resulting in false initially, but any subsequent update makes it true prematurely

Your minimal, reproducible example

https://codesandbox.io/p/github/0xdiid/simple-is-fetched-repro/main?import=true

Steps to reproduce

Steps are in the repro app itself, but a quick copypaste here:

  1. Click "1. Prefetch Query" - Creates query with undefined data, but starts fetching with a 3 second delay
  2. Click "2. Mount Observer with initialData" - Triggers the bug (if pressed before 3 seconds)
  3. If you clicked 2 before 3 seconds, you should see isFetchedAfterMount be true which is not expected
  4. You can now click "3. Reset" to reset the state and wait for 3 seconds after clicking 1 to see flags set "properly"

Expected behavior

As a user, I expect isFetchedAfterMount to only trigger when the data is fetched from outside of the persisted cache, which matches previous implementations

How often does this bug happen?

Every time

Screenshots or Videos

Screen.Recording.2025-09-15.at.9.45.47.PM.mov

Platform

  • OS: mac
  • Browser: chrome
  • Version: 140.0

Tanstack Query adapter

react-query

TanStack Query version

v5.87.1

TypeScript version

v5.9.2

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions