diff --git a/.changeset/solid-query-suspense-ensure-data.md b/.changeset/solid-query-suspense-ensure-data.md
new file mode 100644
index 00000000000..d1d72d27018
--- /dev/null
+++ b/.changeset/solid-query-suspense-ensure-data.md
@@ -0,0 +1,5 @@
+---
+'@tanstack/solid-query': patch
+---
+
+fix(solid-query): avoid triggering Suspense when data is already cached (e.g. via `ensureQueryData`)
diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx
index b2df435dfc2..eadd501984f 100644
--- a/packages/solid-query/src/__tests__/suspense.test.tsx
+++ b/packages/solid-query/src/__tests__/suspense.test.tsx
@@ -908,6 +908,47 @@ describe("useQuery's in Suspense mode", () => {
consoleMock.mockRestore()
})
+ // https://github.com/TanStack/query/issues/9955
+ it('should not trigger Suspense when data was preloaded via ensureQueryData', async () => {
+ const key = queryKey()
+
+ const ensurePromise = queryClient.ensureQueryData({
+ queryKey: key,
+ queryFn: () => sleep(10).then(() => 'preloaded'),
+ staleTime: Infinity,
+ })
+ await vi.advanceTimersByTimeAsync(10)
+ await ensurePromise
+
+ let fallbackMounted = false
+
+ function Page() {
+ const state = useQuery(() => ({
+ queryKey: key,
+ queryFn: () => sleep(10).then(() => 'fresh'),
+ staleTime: Infinity,
+ }))
+
+ return
data: {state.data}
+ }
+
+ function Fallback() {
+ fallbackMounted = true
+ return <>loading>
+ }
+
+ const rendered = render(() => (
+
+ }>
+
+
+
+ ))
+
+ expect(rendered.getByText('data: preloaded')).toBeInTheDocument()
+ expect(fallbackMounted).toBe(false)
+ })
+
it('should render the correct amount of times in Suspense mode when gcTime is set to 0', async () => {
const key = queryKey()
let state: UseQueryResult | null = null
diff --git a/packages/solid-query/src/useBaseQuery.ts b/packages/solid-query/src/useBaseQuery.ts
index 773d0719e0c..e45063d123a 100644
--- a/packages/solid-query/src/useBaseQuery.ts
+++ b/packages/solid-query/src/useBaseQuery.ts
@@ -10,6 +10,7 @@ import {
createSignal,
on,
onCleanup,
+ untrack,
} from 'solid-js'
import { createStore, reconcile, unwrap } from 'solid-js/store'
import { useQueryClient } from './QueryClientProvider'
@@ -377,6 +378,14 @@ export function useBaseQuery<
): any {
if (prop === 'data') {
if (state.data !== undefined) {
+ // When data is already in the store and no fetch is in-flight (e.g.
+ // it was preloaded via `ensureQueryData`), avoid reading the resource
+ // because its initial pending state would otherwise trigger Suspense
+ // on the synchronous-resolve microtask gap. See #9955.
+ // `untrack` keeps `isFetching` from leaking into the data subscriber.
+ if (!untrack(() => state.isFetching)) {
+ return state.data
+ }
return queryResource.latest?.data
}
return queryResource()?.data