Skip to content

Commit ffb11b3

Browse files
authored
fix(solid-query): Fix race condition issues with createQuery (#7748)
* fix(solid-query): Fix race condition issues with `createQuery`
1 parent c101251 commit ffb11b3

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

packages/solid-query/src/__tests__/createQuery.test.tsx

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3528,6 +3528,124 @@ describe('createQuery', () => {
35283528
])
35293529
})
35303530

3531+
// See https://github.com/TanStack/query/issues/7711
3532+
it('race condition: should cleanup observers after component that created the query is unmounted #1', async () => {
3533+
const key = queryKey()
3534+
3535+
function Component() {
3536+
let val = 1
3537+
const dataQuery = createQuery(() => ({
3538+
queryKey: [key],
3539+
queryFn: () => {
3540+
return val++
3541+
},
3542+
}))
3543+
3544+
return (
3545+
<div>
3546+
<p>component</p>
3547+
<p>data: {String(dataQuery.data)}</p>
3548+
</div>
3549+
)
3550+
}
3551+
3552+
const Outer = () => {
3553+
const [showComp, setShowComp] = createSignal(true)
3554+
return (
3555+
<div>
3556+
<button
3557+
onClick={() => {
3558+
queryClient.invalidateQueries()
3559+
setShowComp(!showComp())
3560+
}}
3561+
>
3562+
toggle
3563+
</button>
3564+
{showComp() ? <Component /> : <div>not showing</div>}
3565+
</div>
3566+
)
3567+
}
3568+
3569+
const rendered = render(() => (
3570+
<QueryClientProvider client={queryClient}>
3571+
<Outer />
3572+
</QueryClientProvider>
3573+
))
3574+
3575+
await waitFor(() => rendered.getByText('component'))
3576+
fireEvent.click(rendered.getByText('toggle'))
3577+
await waitFor(() => rendered.getByText('not showing'))
3578+
fireEvent.click(rendered.getByText('toggle'))
3579+
await waitFor(() => rendered.getByText('component'))
3580+
fireEvent.click(rendered.getByText('toggle'))
3581+
await waitFor(() => rendered.getByText('not showing'))
3582+
3583+
const entry = queryClient.getQueryCache().find({
3584+
queryKey: [key],
3585+
})!
3586+
3587+
expect(entry.getObserversCount()).toBe(0)
3588+
})
3589+
3590+
// See https://github.com/TanStack/query/issues/7711
3591+
it('race condition: should cleanup observers after component that created the query is unmounted #2', async () => {
3592+
const key = queryKey()
3593+
3594+
function Component() {
3595+
let val = 1
3596+
const dataQuery = createQuery(() => ({
3597+
queryKey: [key],
3598+
queryFn: () => {
3599+
return val++
3600+
},
3601+
}))
3602+
3603+
return (
3604+
<div>
3605+
<p>component</p>
3606+
<p>data: {String(dataQuery.data)}</p>
3607+
</div>
3608+
)
3609+
}
3610+
3611+
const Outer = () => {
3612+
const [showComp, setShowComp] = createSignal(true)
3613+
return (
3614+
<div>
3615+
<button
3616+
onClick={() => {
3617+
queueMicrotask(() => setShowComp(!showComp()))
3618+
queryClient.invalidateQueries()
3619+
}}
3620+
>
3621+
toggle
3622+
</button>
3623+
{showComp() ? <Component /> : <div>not showing</div>}
3624+
</div>
3625+
)
3626+
}
3627+
3628+
const rendered = render(() => (
3629+
<QueryClientProvider client={queryClient}>
3630+
<Outer />
3631+
</QueryClientProvider>
3632+
))
3633+
3634+
await waitFor(() => rendered.getByText('component'))
3635+
fireEvent.click(rendered.getByText('toggle'))
3636+
await waitFor(() => rendered.getByText('not showing'))
3637+
fireEvent.click(rendered.getByText('toggle'))
3638+
await waitFor(() => rendered.getByText('component'))
3639+
fireEvent.click(rendered.getByText('toggle'))
3640+
await waitFor(() => rendered.getByText('not showing'))
3641+
3642+
const entry = queryClient.getQueryCache().find({
3643+
queryKey: [key],
3644+
})!
3645+
3646+
expect(entry.getObserversCount()).toBe(0)
3647+
})
3648+
35313649
it('should mark query as fetching, when using initialData', async () => {
35323650
const key = queryKey()
35333651
const results: Array<DefinedCreateQueryResult<string>> = []

packages/solid-query/src/createBaseQuery.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,11 @@ export function createBaseQuery<
179179
const obs = observer()
180180
return obs.subscribe((result) => {
181181
observerResult = result
182-
queueMicrotask(() => refetch())
182+
queueMicrotask(() => {
183+
if (unsubscribe) {
184+
refetch()
185+
}
186+
})
183187
})
184188
}
185189

0 commit comments

Comments
 (0)