query icon indicating copy to clipboard operation
query copied to clipboard

Angular Query: Query gets stuck in isRefetching state forever in an edge-case

Open shessafridi opened this issue 1 year ago • 5 comments

Describe the bug

The isRefetching signal on the query stays on true even when the query finishes refetching.

This issue happens when a disabled query is enabled and immediately refetched with the refetch method on the query and the data is fresh in the cache, it doesn't happen on stale queries.

This bug does not happen on version 5.16.1, I discovered it after updating from 5.16.1 to the latest version 5.17.19, I am not sure exactly which version introduced this bug.

For Example:

  ngOnInit() {
    this.id.set('123');
    this.query.refetch();
  }

Setting the id signal would enable the query and calling refetch immediately after will cause the bug to happen, but wrapping the refetch call in a setTimeout of even 0 delay would prevent the issue from happening

Your minimal, reproducible example

https://github.com/shessafridi/angular-query-refetch-bug

Steps to reproduce

Repro Steps

  1. There are 2 links on the main page "TestA" and "TestB"
  2. Click "TestA" to load it's data, then click "TestB" to load it's data
  3. Go back to the "TestA" link
  4. You will see that the query is stuck in isRefetching state forever

Expected behavior

The query signals should reflect what is in the devtools

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

OS: Windows 11 Browser: Chrome

Angular Version: 17.0.0 Angular Query: 5.17.19

Tanstack Query adapter

angular-query

TanStack Query version

5.17.19

TypeScript version

~5.2.2

Additional context

No response

shessafridi avatar Jan 25 '24 23:01 shessafridi

Hi @shessafridi the code in ngOnInit is not doing what it looks like.

  id = signal('');

  query = injectQuery(() => ({
    enabled: !!this.id(),
    queryKey: ['test', this.id()],
    queryFn: () => sleep(2000).then(() => 'Test ' + this.id()),
    staleTime: ms('1y'),
  }));

  ngOnInit() {
    this.id.set('a');
    this.query.refetch();
  }

First, the id signal is changed. This schedules an effect to run inside the TanStack Query Angular adapter. Effects are asynchronous. Until this effect is run the query is not changed. Second, refetch() is called on this unchanged query. It is disabled but refetch() can be used to run a disabled query manually. The queryKey will be just 'test' as id was an empty string when the query was instantiated. Third, when the effect is run the query observer is given the new options including the new id signal value resulting in an updated query instance and queryFn is run.

Indeed the signals from Angular Query are not correct in this case which I did find a fix for but I have to check if that doesn't cause other issues. I am curious for the use case of both running refetch manually and enabling the query making it run automatically?

arnoud-dv avatar Apr 12 '24 21:04 arnoud-dv

Did find this somewhat related Vue Query issue.

arnoud-dv avatar Apr 12 '24 22:04 arnoud-dv

Thank you for the insight, this is indeed a rare issue, I found it in a component haphazardly refactored to use TanStack Query, I can't think of a real use case for something like this but it was improper usage of TanStack Query on my end that brought the issue to light.

shessafridi avatar Apr 15 '24 11:04 shessafridi

Did find this somewhat related Vue Query issue.

I'm unfamiliar with Vue, but that seems somewhat related.

shessafridi avatar Apr 15 '24 11:04 shessafridi