Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

solid-query: switching the queryClient accessor strands the new client's cache (subscription stays on the old observer)

Aperta Adatta ai principianti
#11,106 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@MaNaN1803 ci sta già lavorando.

Dal 23/7/2026.

  • #1 di @MaNaN1803 — aperta
  • #11111 di @rohanpatel2002 — chiusa senza merge
  • #11615 di @ousamabenyounes — chiusa senza merge
  • #11920 di @taekop — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
84/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Tranquilla
Stack tecnologico
typescript
Ambito
frontend

Direzione di ricerca

Leggi packages/solid-query/src/useBaseQuery.ts nelle sezioni intorno a createClientSubscriber e client-change computed, quindi esegui packages/solid-query/src/tests/useQuery.test.tsx con il test queryClient-change. Il lavoro è completato quando la cache del nuovo client riceve il valore recuperato e l’hook esegue il rendering di quel valore dopo il passaggio da un client all’altro.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the bug

When the queryClient accessor passed to useQuery (second argument) switches to a different QueryClient, the hook never actually moves to the new client:

  • the refetch triggered by the switch lands in the previous client's cache (its dataUpdateCount increments),
  • the entry created in the new client's cache stays status: 'pending' / fetchStatus: 'idle' forever and never receives data,
  • the hook keeps rendering results coming from the old observer, so the UI shows the old client's data while claiming the new client is active.

The root cause is an ordering issue in useBaseQuery. createClientSubscriber captures the observer eagerly when called (useBaseQuery.ts#L180-L181):

const createClientSubscriber = () => {
  const obs = observer() // reads the signal NOW
  return obs.subscribe(/* ... */)
}

but in the client-change computed it is called before setObserver(newObserver) (useBaseQuery.ts#L317-L332):

createComputed(
  on(client, (c) => {
    if (unsubscribe) {
      unsubscribe()
    }
    const newObserver = new Observer(c, defaultedOptions())
    unsubscribe = createClientSubscriber() // observer() still returns the OLD observer
    setObserver(newObserver)
  }, { defer: true }),
)

So the fresh subscription attaches to the old observer. Re-subscribing to the old (now stale) observer triggers its onSubscribe → a refetch against the old client's cache — which is where the second queryFn call comes from. The new observer ends up with zero subscribers, and a QueryObserver without subscribers never fetches, so the new client's cache entry is stranded.

Swapping the two lines (setObserver(newObserver) first, then unsubscribe = createClientSubscriber()) makes the new client's cache receive the data, with no regressions in the rest of the solid-query suite.

The existing test for this scenario (useQuery → "should refetch query when queryClient changes") passes only because it asserts toBeDefined() on the new client's cache entry — which is satisfied by the stranded pending entry. Tightening it to the exact cached value exposes the bug (see the repro branch below); this is the site I intentionally left loose in #11105.

Your minimal, reproducible example

https://stackblitz.com/github/reizam/query/tree/repro/solid-client-switch-observer/examples/solid/client-switch-repro

(Alternatively, the same branch tightens the existing unit test into a failing repro: useQuery.test.tsx#L5755-L5760 — run pnpm vitest run useQuery.test.tsx -t "should refetch query when queryClient changes" in packages/solid-query.)

Steps to reproduce
  1. Open the StackBlitz example. The query fetches once through client 1 (both cache snapshots are rendered live).
  2. Click "Switch to client 2".
  3. Observe:
    • queryFn runs a second time, but client 1's cache receives the result (dataUpdateCount: 2),
    • client 2's cache entry stays status=pending fetchStatus=idle data=undefined indefinitely,
    • the useQuery result renders "result of fetch #2" — data owned by client 1 — while the active client is client 2.
Expected behavior

After the queryClient accessor switches, the query should run against the new client: its cache entry should receive the data, and the hook should be subscribed to the new observer.

How often does this bug happen?

Every time

Screenshots or Videos

State rendered by the repro after the switch:

client 1 cache: status=success fetchStatus=idle data="result of fetch #2" dataUpdateCount=2
client 2 cache: status=pending fetchStatus=idle data=undefined dataUpdateCount=0
Platform
  • OS: macOS
  • Browser: Chrome (also reproduced in the vitest/jsdom suite)
Tanstack Query adapter

solid-query

TanStack Query version

v5.101.4

TypeScript version

v5.9.3

Additional context

Fix ready (the reorder described above) plus the tightened assertion as a regression test. Happy to send a PR.

Lingua principale
TypeScript
Stelle
50.4k
Fork
4.2k
Merge medio
7h 29m
PR unite (30g)
393

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di TanStack/query

Tutte le issue di TanStack/query

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.