QueryClient.isFetching and useIsFetching accept a fetchStatus filter and ignore it
Mantenedores costumam responder em até 1 dia
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- 1-3 horas
- Facilidade para iniciantes
- 78/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Ativa
- Stack de tecnologia
- react, typescript
- Domínio
- backend-api-design
Direção de pesquisa
Comece em packages/query-core/src/queryClient.ts, onde a issue aponta o spread e a sobrescrita de fetchStatus em isFetching; em seguida, acompanhe como useIsFetching encaminha seus filtros. Leia os testes relacionados a QueryClient.isFetching e useIsFetching e adicione cobertura para os casos pausados e inativos relatados. O trabalho estará concluído quando a API respeitar o filtro ou o rejeitar nos tipos, com comportamento e documentação consistentes.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Describe the bug
QueryFilters has a fetchStatus?: FetchStatus field, and FetchStatus is 'fetching' | 'paused' | 'idle', so isFetching({ fetchStatus: 'paused' }) type-checks. It has no effect: QueryClient.isFetching spreads the filters it is given and then writes its own fetchStatus over them, so the argument is discarded for every value, not only 'paused'.
QueryCache.findAll honours the same filter correctly, which makes the difference easy to miss — the filter works through one entry point and is silently dropped through the other.
Minimal reproduction
import { QueryClient } from '@tanstack/query-core'
const client = new QueryClient()
const queryKey = ['session']
const cache = client.getQueryCache()
const query = cache.build(client, { queryKey, queryFn: async () => 'x' })
query.setState({ fetchStatus: 'paused' })
console.log(cache.find({ queryKey })?.state.fetchStatus) // 'paused'
console.log(cache.findAll({ queryKey, fetchStatus: 'paused' }).length) // 1
console.log(client.isFetching({ queryKey, fetchStatus: 'paused' })) // 0
console.log(client.isFetching({ queryKey, fetchStatus: 'idle' })) // 0
Expected / actual
| call | expected | actual |
|---|---|---|
findAll({ fetchStatus: 'paused' }).length |
1 | 1 |
isFetching({ fetchStatus: 'paused' }) |
1, or a type error | 0 |
isFetching({ fetchStatus: 'idle' }) |
1, or a type error | 0 |
Either outcome would be fine. What is awkward is a public, typed, documented parameter that is accepted and does nothing.
Cause
packages/query-core/src/queryClient.ts:
isFetching(filters) {
return this.#queryCache.findAll({ ...filters, fetchStatus: 'fetching' }).length
}
useIsFetching forwards its filters to this method, so it behaves the same way.
Why it came up
An app that asks "is this query still waiting on the network" wants paused to count: a lookup held because the browser is offline, or because the window is unfocused and the retry is deferred, has not answered yet. Reading it through useIsFetching({ queryKey, fetchStatus: 'paused' }) compiles and quietly answers 0, so the UI treats a waiting query as a settled one. In our case a page showed a "not found" state to someone whose session lookup was merely paused.
The workaround is to subscribe to the cache and use findAll directly, which works but means reimplementing what useIsFetching exists to provide.
Possible resolutions
In rough order of how little they change:
- Type it out — omit
fetchStatusfrom the filters these two accept, so passing it is a compile error, and say in the reference that they count fetching queries only. - Honour it — use the caller's
fetchStatuswhen one is given and default to'fetching'otherwise. This changes behaviour for anyone currently passing a value and relying on it being ignored, which seems unlikely but is a real semver consideration. - Leave the behaviour and document it — note on
useIsFetchingandQueryClient.isFetchingthatfetchStatusis fixed, and point atgetQueryCache().findAllfor other statuses.
Happy to send a PR for whichever you prefer.
Related
- Discussion #6756 proposes a built-in
queryClient.isPaused/useIsPaused, and its example hook uses the same spread-then-override pattern in user code. If that proposal is the intended answer, this is the part of it that bites today — and option 1 or 3 above would stop the current API misleading people in the meantime. - #7559 and #8531 are about
isFetchingreporting the wrong thing for fetching queries; this is narrower, about a filter argument being inert.
Environment
@tanstack/query-core5.104.1- Node 26.11.1, TypeScript 6.0.3
- Reproduced with
query-corealone, so no framework adapter is involved
- Linguagem predominante
- TypeScript
- Estrelas
- 50.4k
- Forks
- 4.2k
- Merge médio
- 8h 32min
- PRs com merge (30d)
- 408
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de TanStack/query
-
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery)Talvez livre de novo @LeonxLJX assumiu há 40 dias e não há nenhum pull request aberto. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
TanStack/query#11358 · 2 comentários · 1 reação ·
Mantenedores costumam responder em até 1 dia
-
solid-query: switching the queryClient accessor strands the new client's cache (subscription stays on the old observer)Talvez já em andamento @MaNaN1803 assumiu há 83 dias. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
TanStack/query#11106 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
restoreQueries and persisterGc throw on malformed persisted entriesTalvez já em andamento @VGontier-cmd assumiu há 8 dias. Aberta
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 72/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 45/100
Mantenedores costumam responder em até 1 dia
-
setQueryData: NoInfer loses discriminated-union members when spreading a narrowed updater valueTalvez já em andamento @iosayin assumiu há 9 dias. Aberta
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 55/100
Mantenedores costumam responder em até 1 dia
Todas as issues de TanStack/query
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
Mantenedores costumam responder em até 1 dia
-
high priority
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
CI-CMG/deep-sea-corals-exb#84 · 1 comentário ·
-
Create/import wallet form shows raw "password must be at least 1 characters" instead of the translated messageTalvez já em andamento @CapThunder19 assumiu hoje. Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
joinmarket-webui/jam#1538 ·
Mantenedores costumam responder em até 1 dia
-
t0ggles
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
nolimits4web/swiper#8240 · 1 comentário ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
Mantenedores costumam responder em até 1 dia