Skip to content

fix(solid-query): resolve query client outside memos - #10571

Merged
TkDodo merged 4 commits into
TanStack:mainfrom
KimHyeongRae0:fix/10445-solid-query-client-resolver
Aug 18, 2026
Merged

fix(solid-query): resolve query client outside memos#10571
TkDodo merged 4 commits into
TanStack:mainfrom
KimHyeongRae0:fix/10445-solid-query-client-resolver

Conversation

@KimHyeongRae0

@KimHyeongRae0 KimHyeongRae0 commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Changes

Closes #10445.

Solid hooks no longer call useQueryClient from inside createMemo. useQueryClientResolver captures QueryClientContext at hook top level, then affected hooks call the returned accessor from memos.

This keeps explicit queryClient accessors reactive and leaves the existing useQueryClient(client) API unchanged.

Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

Local verification:

  • pnpm --filter @tanstack/solid-query test:lib
  • pnpm --filter @tanstack/solid-query test:types:tscurrent
  • pnpm --filter @tanstack/solid-query test:eslint

Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes

    • Improved query client resolution within reactive callbacks.
    • Hooks now correctly resubscribe when a reactive custom query client changes.
    • Missing query client errors are reported when the resolver is invoked.
  • Tests

    • Added coverage for reactive resolution and custom client switching.
  • Chores

    • Added a patch release changeset for Solid Query.

@coderabbitai

coderabbitai Bot commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 65980a1e-5228-4425-aa60-2a5ec83a127a

📥 Commits

Reviewing files that changed from the base of the PR and between dce04b5 and e2022ac.

📒 Files selected for processing (11)
  • .changeset/solid-query-client-resolver.md
  • packages/solid-query/src/QueryClientProvider.tsx
  • packages/solid-query/src/__tests__/QueryClientProvider.test.tsx
  • packages/solid-query/src/__tests__/useIsFetching.test.tsx
  • packages/solid-query/src/__tests__/useIsMutating.test.tsx
  • packages/solid-query/src/useBaseQuery.ts
  • packages/solid-query/src/useIsFetching.ts
  • packages/solid-query/src/useIsMutating.ts
  • packages/solid-query/src/useMutation.ts
  • packages/solid-query/src/useMutationState.ts
  • packages/solid-query/src/useQueries.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • .changeset/solid-query-client-resolver.md
  • packages/solid-query/src/tests/QueryClientProvider.test.tsx
  • packages/solid-query/src/useIsMutating.ts
  • packages/solid-query/src/useMutationState.ts
  • packages/solid-query/src/useBaseQuery.ts
  • packages/solid-query/src/useMutation.ts
  • packages/solid-query/src/tests/useIsMutating.test.tsx
  • packages/solid-query/src/useIsFetching.ts
  • packages/solid-query/src/tests/useIsFetching.test.tsx
  • packages/solid-query/src/QueryClientProvider.tsx
  • packages/solid-query/src/useQueries.ts

Included review availability: Your plan includes up to 10 reviews per rolling hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Adds useQueryClientResolver and updates Solid Query hooks to resolve context at hook scope. Reactive computations use the returned accessor. Fetching and mutation subscriptions now resubscribe when the client changes.

Changes

Solid QueryClient resolution

Layer / File(s) Summary
Resolver contract and context errors
packages/solid-query/src/QueryClientProvider.tsx, packages/solid-query/src/__tests__/QueryClientProvider.test.tsx
Adds the shared missing-client error and exports useQueryClientResolver. Tests cover reactive invocation and deferred missing-provider errors.
Hook client resolution and subscription lifecycle
packages/solid-query/src/useBaseQuery.ts, packages/solid-query/src/useQueries.ts, packages/solid-query/src/useMutation.ts, packages/solid-query/src/useMutationState.ts, packages/solid-query/src/useIsFetching.ts, packages/solid-query/src/useIsMutating.ts
Moves context resolution outside reactive memo callbacks. Fetching and mutation cache subscriptions now run in effects and clean up when the resolved client changes.
Reactive client switching validation
packages/solid-query/src/__tests__/useIsFetching.test.tsx, packages/solid-query/src/__tests__/useIsMutating.test.tsx
Tests unsubscribe and resubscribe behavior when a reactive custom QueryClient changes.
Release metadata
.changeset/solid-query-client-resolver.md
Adds a patch changeset for the resolver change.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to e2022

This localized Solid Query change resolves query-client access outside reactive memos while preserving explicit client behavior; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary change: resolving the Solid Query client outside reactive memos.
Description check ✅ Passed The description includes the required change summary, checklist, release impact, changeset status, and verification details.
Linked Issues check ✅ Passed The changes resolve query clients at hook scope across the affected Solid hooks and preserve reactive explicit clients as required by [#10445].
Out of Scope Changes check ✅ Passed The changeset, implementation updates, and regression tests are directly related to resolving query clients outside reactive memos.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@nx-cloud

nx-cloud Bot commented Apr 25, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit e2022ac

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 4m 50s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 10s View ↗

☁️ Nx Cloud last updated this comment at 2026-08-17 20:04:28 UTC

@pkg-pr-new

pkg-pr-new Bot commented Apr 25, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10571

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10571

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@10571

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10571

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10571

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10571

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10571

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10571

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10571

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10571

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10571

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10571

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10571

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10571

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10571

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10571

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10571

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10571

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10571

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10571

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10571

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10571

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10571

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10571

commit: e2022ac

@KimHyeongRae0
KimHyeongRae0 marked this pull request as ready for review May 2, 2026 12:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
packages/solid-query/src/useIsMutating.ts (1)

11-23: ⚡ Quick win

Same subscription-reactivity gap as useIsFetching — wrap in createEffect.

mutationCache().subscribe(...) at line 19 is called once at initialization. If client changes, the subscription won't follow the new mutation cache. Apply the same createEffect-based pattern used in useMutationState:

♻️ Suggested fix
-  const [mutations, setMutations] = createSignal(
-    client().isMutating(filters?.()),
-  )
-
-  const unsubscribe = mutationCache().subscribe((_result) => {
-    setMutations(client().isMutating(filters?.()))
-  })
-
-  onCleanup(unsubscribe)
+  const [mutations, setMutations] = createSignal(0)
+
+  createEffect(() => {
+    setMutations(client().isMutating(filters?.()))
+    const unsubscribe = mutationCache().subscribe(() => {
+      setMutations(client().isMutating(filters?.()))
+    })
+    onCleanup(unsubscribe)
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/useIsMutating.ts` around lines 11 - 23, The
subscription to mutationCache in useIsMutating is created once and won't track
changes if the resolved client changes; wrap the subscription logic in a
createEffect (like useMutationState) that reads resolveClient()/client() and
mutationCache() so it re-subscribes when client changes, call
setMutations(client().isMutating(filters?.())) inside the effect, and ensure you
call onCleanup to unsubscribe the previous mutationCache.subscribe; update
functions/variables involved: resolveClient, client, mutationCache,
setMutations, createEffect, and onCleanup so the subscription follows client
changes.
packages/solid-query/src/useMutation.ts (1)

24-25: ⚖️ Poor tradeoff

client memo is only read at initialization; client changes won't be reflected in the observer.

client (line 25) is read once at line 32 to construct MutationObserver. There is no reactive listener (e.g. createComputed(on(client, ...))) that would recreate the observer if the resolved QueryClient changes later. This is pre-existing behavior, but unlike useBaseQuery which handles client-swap via on(client, ...), useMutation silently continues using the original client.

Worth tracking in a follow-up if dynamic client swapping needs to be supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/useMutation.ts` around lines 24 - 25, The
MutationObserver in useMutation is constructed once using the memoized client
(client = createMemo(() => resolveClient())) and never updated if the resolved
QueryClient changes; modify useMutation so it watches the client memo and
recreates/updates the MutationObserver when client changes (similar to
useBaseQuery's on(client, ...) pattern): use a reactive listener (e.g.,
createComputed(on(client, ...))) inside useMutation to dispose the old
MutationObserver and instantiate a new MutationObserver bound to the new
resolveClient() result so the observer always uses the current QueryClient.
packages/solid-query/src/useIsFetching.ts (1)

11-21: ⚡ Quick win

Subscription doesn't react to client changes — inconsistent with useMutationState.

The queryCache().subscribe(...) call at line 17 is established once, outside any reactive scope. If client changes (e.g. the provider swaps its QueryClient), queryCache recomputes but the subscription stays bound to the old cache. useMutationState avoids this correctly by wrapping its subscription in createEffect:

createEffect(() => {
  const unsubscribe = mutationCache().subscribe(...)
  onCleanup(unsubscribe)
})

This PR makes client correctly reactive for the first time (fixing the useContext-in-memo bug), so this latent subscription gap is now more likely to surface.

♻️ Suggested fix
-  const [fetches, setFetches] = createSignal(client().isFetching(filters?.()))
-
-  const unsubscribe = queryCache().subscribe(() => {
-    setFetches(client().isFetching(filters?.()))
-  })
-
-  onCleanup(unsubscribe)
+  const [fetches, setFetches] = createSignal(0)
+
+  createEffect(() => {
+    setFetches(client().isFetching(filters?.()))
+    const unsubscribe = queryCache().subscribe(() => {
+      setFetches(client().isFetching(filters?.()))
+    })
+    onCleanup(unsubscribe)
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/useIsFetching.ts` around lines 11 - 21, The
subscription to queryCache is created once and won't update when the reactive
client/queryCache changes; wrap the subscribe/unsubscribe logic in a reactive
scope (e.g. createEffect) so it re-subscribes whenever client() or queryCache()
changes and ensure onCleanup unsubscribes the previous listener; specifically,
move the queryCache().subscribe(...) and its onCleanup into a createEffect that
reads queryCache() (or client()) and also re-evaluates
setFetches(client().isFetching(filters?.())) inside the effect so fetches
updates immediately when client, queryCache or filters change (referencing
resolveClient, client, queryCache, setFetches).
packages/solid-query/src/__tests__/QueryClientProvider.test.tsx (1)

180-201: ⚡ Quick win

Add a test for useQueryClientResolver when no QueryClientProvider is present.

The PR's linked issue (#10445) explicitly lists "ensure resolver avoids throws when context is missing/late" as a required test, but no such case is covered here. The existing suite only validates the happy path. It's unclear from the test file alone whether useQueryClientResolver() without a provider throws (like useQueryClient() does), silently returns undefined, or behaves differently — and the expected contract should be locked down by a test.

💡 Example test to add
+  describe('useQueryClientResolver', () => {
+    it('should throw when called outside a QueryClientProvider', () => {
+      const consoleMock = vi
+        .spyOn(console, 'error')
+        .mockImplementation(() => undefined)
+
+      function Page() {
+        useQueryClientResolver()
+        return null
+      }
+
+      // Adjust the expectation to match the actual contract (throw vs. safe no-op)
+      expect(() => render(() => <Page />)).toThrow(
+        'No QueryClient set, use QueryClientProvider to set one',
+      )
+
+      consoleMock.mockRestore()
+    })
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/__tests__/QueryClientProvider.test.tsx` around lines
180 - 201, Add a test that verifies useQueryClientResolver is safe when no
provider is present: render a component that captures resolveClient =
useQueryClientResolver() but do not wrap it with <QueryClientProvider>, then
inside a createRoot/createMemo call invoke resolveClient() and assert that
invoking it does not throw and returns undefined (i.e., the resolver handles
missing/late context); reference useQueryClientResolver, QueryClientProvider,
createRoot and createMemo in the test to locate where to add the new case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/solid-query/src/__tests__/QueryClientProvider.test.tsx`:
- Around line 180-201: Add a test that verifies useQueryClientResolver is safe
when no provider is present: render a component that captures resolveClient =
useQueryClientResolver() but do not wrap it with <QueryClientProvider>, then
inside a createRoot/createMemo call invoke resolveClient() and assert that
invoking it does not throw and returns undefined (i.e., the resolver handles
missing/late context); reference useQueryClientResolver, QueryClientProvider,
createRoot and createMemo in the test to locate where to add the new case.

In `@packages/solid-query/src/useIsFetching.ts`:
- Around line 11-21: The subscription to queryCache is created once and won't
update when the reactive client/queryCache changes; wrap the
subscribe/unsubscribe logic in a reactive scope (e.g. createEffect) so it
re-subscribes whenever client() or queryCache() changes and ensure onCleanup
unsubscribes the previous listener; specifically, move the
queryCache().subscribe(...) and its onCleanup into a createEffect that reads
queryCache() (or client()) and also re-evaluates
setFetches(client().isFetching(filters?.())) inside the effect so fetches
updates immediately when client, queryCache or filters change (referencing
resolveClient, client, queryCache, setFetches).

In `@packages/solid-query/src/useIsMutating.ts`:
- Around line 11-23: The subscription to mutationCache in useIsMutating is
created once and won't track changes if the resolved client changes; wrap the
subscription logic in a createEffect (like useMutationState) that reads
resolveClient()/client() and mutationCache() so it re-subscribes when client
changes, call setMutations(client().isMutating(filters?.())) inside the effect,
and ensure you call onCleanup to unsubscribe the previous
mutationCache.subscribe; update functions/variables involved: resolveClient,
client, mutationCache, setMutations, createEffect, and onCleanup so the
subscription follows client changes.

In `@packages/solid-query/src/useMutation.ts`:
- Around line 24-25: The MutationObserver in useMutation is constructed once
using the memoized client (client = createMemo(() => resolveClient())) and never
updated if the resolved QueryClient changes; modify useMutation so it watches
the client memo and recreates/updates the MutationObserver when client changes
(similar to useBaseQuery's on(client, ...) pattern): use a reactive listener
(e.g., createComputed(on(client, ...))) inside useMutation to dispose the old
MutationObserver and instantiate a new MutationObserver bound to the new
resolveClient() result so the observer always uses the current QueryClient.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 80c0bf91-5702-4412-964a-c1bb97f3c67f

📥 Commits

Reviewing files that changed from the base of the PR and between 41a7ab0 and 9e204dc.

📒 Files selected for processing (9)
  • .changeset/solid-query-client-resolver.md
  • packages/solid-query/src/QueryClientProvider.tsx
  • packages/solid-query/src/__tests__/QueryClientProvider.test.tsx
  • packages/solid-query/src/useBaseQuery.ts
  • packages/solid-query/src/useIsFetching.ts
  • packages/solid-query/src/useIsMutating.ts
  • packages/solid-query/src/useMutation.ts
  • packages/solid-query/src/useMutationState.ts
  • packages/solid-query/src/useQueries.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/solid-query/src/__tests__/useIsFetching.test.tsx (1)

264-301: ⚡ Quick win

Make this test verify unsubscribe, not just the displayed count.

The current assertions don’t prove the old queryClient1 query-cache listener was removed. A stale listener would still call back into client() and read the new client after setClient(queryClient2), so this can stay green with a leak. Please assert that the first cache subscription is cleaned up when the client accessor changes.

Example: wrap the first cache subscription and assert its cleanup
   it('should resubscribe when a custom queryClient changes', async () => {
     const queryClient1 = new QueryClient()
     const queryClient2 = new QueryClient()
     const key1 = queryKey()
     const key2 = queryKey()
     const [client, setClient] = createSignal(queryClient1)
+    const queryCache1 = queryClient1.getQueryCache()
+    const originalSubscribe1 = queryCache1.subscribe.bind(queryCache1)
+    const unsubscribe1 = vi.fn()
+
+    vi.spyOn(queryCache1, 'subscribe').mockImplementation((listener) => {
+      const cleanup = originalSubscribe1(listener)
+      return () => {
+        unsubscribe1()
+        cleanup()
+      }
+    })

     function Page() {
       const isFetching = useIsFetching(undefined, client)

       return <div>isFetching: {isFetching()}</div>
@@
     expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()

     setClient(queryClient2)
+    expect(unsubscribe1).toHaveBeenCalledTimes(1)

     expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/__tests__/useIsFetching.test.tsx` around lines 264 -
301, The test should assert that the old QueryClient's cache listener is removed
when the client accessor changes; wrap or spy on
queryClient1.getQueryCache().subscribe (or the subscribe return's unsubscribe
function) before rendering Page (which uses useIsFetching with client accessor),
capture the unsubscribe function or a spy, then after calling
setClient(queryClient2) assert that the unsubscribe was called (or that the
returned subscription is cleaned up) in addition to the displayed count
assertions so you prove the subscription was removed from queryClient1 when Page
switched clients.
packages/solid-query/src/__tests__/useIsMutating.test.tsx (1)

210-245: ⚡ Quick win

Assert old-cache cleanup explicitly in this resubscription test.

This sequence can still pass if the queryClient1 listener leaks, because the stale callback in useIsMutating reads client() when it fires and will see queryClient2 after the swap. Please make the test observe the first subscription’s cleanup directly.

Example: verify the first unsubscribe runs on client switch
   it('should resubscribe when a custom queryClient changes', async () => {
     const queryClient1 = new QueryClient()
     const queryClient2 = new QueryClient()
     const [client, setClient] = createSignal(queryClient1)
+    const mutationCache1 = queryClient1.getMutationCache()
+    const originalSubscribe1 = mutationCache1.subscribe.bind(mutationCache1)
+    const unsubscribe1 = vi.fn()
+
+    vi.spyOn(mutationCache1, 'subscribe').mockImplementation((listener) => {
+      const cleanup = originalSubscribe1(listener)
+      return () => {
+        unsubscribe1()
+        cleanup()
+      }
+    })

     function Page() {
       const isMutating = useIsMutating(undefined, client)

       return <div>mutating: {isMutating()}</div>
@@
     expect(rendered.getByText('mutating: 1')).toBeInTheDocument()

     setClient(queryClient2)
+    expect(unsubscribe1).toHaveBeenCalledTimes(1)

     expect(rendered.getByText('mutating: 0')).toBeInTheDocument()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-query/src/__tests__/useIsMutating.test.tsx` around lines 210 -
245, The test must explicitly assert that the old mutation cache subscription is
cleaned up when swapping clients: wrap or spy on
queryClient1.getMutationCache().subscribe (or the returned unsubscribe) before
rendering Page, record when the unsubscribe is invoked, call
setClient(queryClient2) and assert that the unsubscribe was called (showing the
first subscription was removed) in addition to the existing mutating-count
assertions; reference queryClient1, getMutationCache,
subscribe/returned-unsubscribe, useIsMutating and setClient to locate where to
instrument the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/solid-query/src/__tests__/useIsFetching.test.tsx`:
- Around line 264-301: The test should assert that the old QueryClient's cache
listener is removed when the client accessor changes; wrap or spy on
queryClient1.getQueryCache().subscribe (or the subscribe return's unsubscribe
function) before rendering Page (which uses useIsFetching with client accessor),
capture the unsubscribe function or a spy, then after calling
setClient(queryClient2) assert that the unsubscribe was called (or that the
returned subscription is cleaned up) in addition to the displayed count
assertions so you prove the subscription was removed from queryClient1 when Page
switched clients.

In `@packages/solid-query/src/__tests__/useIsMutating.test.tsx`:
- Around line 210-245: The test must explicitly assert that the old mutation
cache subscription is cleaned up when swapping clients: wrap or spy on
queryClient1.getMutationCache().subscribe (or the returned unsubscribe) before
rendering Page, record when the unsubscribe is invoked, call
setClient(queryClient2) and assert that the unsubscribe was called (showing the
first subscription was removed) in addition to the existing mutating-count
assertions; reference queryClient1, getMutationCache,
subscribe/returned-unsubscribe, useIsMutating and setClient to locate where to
instrument the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2916fe7e-3bfa-4ba1-adb1-64a361016163

📥 Commits

Reviewing files that changed from the base of the PR and between 9e204dc and 0843b31.

📒 Files selected for processing (5)
  • packages/solid-query/src/__tests__/QueryClientProvider.test.tsx
  • packages/solid-query/src/__tests__/useIsFetching.test.tsx
  • packages/solid-query/src/__tests__/useIsMutating.test.tsx
  • packages/solid-query/src/useIsFetching.ts
  • packages/solid-query/src/useIsMutating.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/solid-query/src/tests/QueryClientProvider.test.tsx
  • packages/solid-query/src/useIsFetching.ts

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@TkDodo
TkDodo merged commit 47d49d3 into TanStack:main Aug 18, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useQueryClient / useContext runs inside createMemo, breaking Solid rules and causing undefined QueryClient (e.g. defaultQueryOptions on lazy routes)

2 participants