Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/solid-query-client-resolver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/solid-query': patch
---

Resolve the query client context outside reactive memo callbacks.
26 changes: 24 additions & 2 deletions packages/solid-query/src/QueryClientProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,47 @@ import {
useContext,
} from 'solid-js'
import type { QueryClient } from './QueryClient'
import type { JSX } from 'solid-js'
import type { Accessor, JSX } from 'solid-js'

export const QueryClientContext = createContext<
(() => QueryClient) | undefined
>(undefined)

const queryClientContextError =
'No QueryClient set, use QueryClientProvider to set one'

export const useQueryClient = (queryClient?: QueryClient) => {
if (queryClient) {
return queryClient
}
const client = useContext(QueryClientContext)

if (!client) {
throw new Error('No QueryClient set, use QueryClientProvider to set one')
throw new Error(queryClientContextError)
}

return client()
}

export const useQueryClientResolver = (
queryClient?: Accessor<QueryClient | undefined>,
): Accessor<QueryClient> => {
const contextClient = useContext(QueryClientContext)

return () => {
const resolvedClient = queryClient?.()
if (resolvedClient) {
return resolvedClient
}

if (!contextClient) {
throw new Error(queryClientContextError)
}

return contextClient()
}
}

export type QueryClientProviderProps = {
client: QueryClient
children?: JSX.Element
Expand Down
25 changes: 25 additions & 0 deletions packages/solid-query/src/__tests__/QueryClientProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { render } from '@solidjs/testing-library'
import { QueryCache } from '@tanstack/query-core'
import { queryKey, sleep } from '@tanstack/query-test-utils'
import { createMemo, createRoot } from 'solid-js'
import { QueryClient, QueryClientProvider, useQuery, useQueryClient } from '..'
import { useQueryClientResolver } from '../QueryClientProvider'

describe('QueryClientProvider', () => {
beforeEach(() => {
Expand Down Expand Up @@ -174,4 +176,27 @@ describe('QueryClientProvider', () => {

consoleMock.mockRestore()
})

it('creates a query client resolver that is safe to call in reactive callbacks', () => {
const queryClient = new QueryClient()
let resolveClient!: () => QueryClient

function Page() {
resolveClient = useQueryClientResolver()
return null
}

render(() => (
<QueryClientProvider client={queryClient}>
<Page />
</QueryClientProvider>
))

createRoot((dispose) => {
const client = createMemo(() => resolveClient())

expect(client()).toBe(queryClient)
dispose()
})
})
})
5 changes: 3 additions & 2 deletions packages/solid-query/src/useBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
onCleanup,
} from 'solid-js'
import { createStore, reconcile, unwrap } from 'solid-js/store'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import { useIsRestoring } from './isRestoring'
import type { UseBaseQueryOptions } from './types'
import type { Accessor, Signal } from 'solid-js'
Expand Down Expand Up @@ -115,7 +115,8 @@ export function useBaseQuery<
) {
type ResourceData = QueryObserverResult<TData, TError>

const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())
const isRestoring = useIsRestoring()
// There are times when we run a query on the server but the resource is never read
// This could lead to times when the queryObserver is unsubscribed before the resource has loaded
Expand Down
5 changes: 3 additions & 2 deletions packages/solid-query/src/useIsFetching.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createMemo, createSignal, onCleanup } from 'solid-js'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import type { QueryFilters } from '@tanstack/query-core'
import type { QueryClient } from './QueryClient'
import type { Accessor } from 'solid-js'
Expand All @@ -8,7 +8,8 @@ export function useIsFetching(
filters?: Accessor<QueryFilters>,
queryClient?: Accessor<QueryClient>,
): Accessor<number> {
const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())
const queryCache = createMemo(() => client().getQueryCache())

const [fetches, setFetches] = createSignal(client().isFetching(filters?.()))
Expand Down
5 changes: 3 additions & 2 deletions packages/solid-query/src/useIsMutating.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createMemo, createSignal, onCleanup } from 'solid-js'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import type { MutationFilters } from '@tanstack/query-core'
import type { QueryClient } from './QueryClient'
import type { Accessor } from 'solid-js'
Expand All @@ -8,7 +8,8 @@ export function useIsMutating(
filters?: Accessor<MutationFilters>,
queryClient?: Accessor<QueryClient>,
): Accessor<number> {
const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())
const mutationCache = createMemo(() => client().getMutationCache())

const [mutations, setMutations] = createSignal(
Expand Down
5 changes: 3 additions & 2 deletions packages/solid-query/src/useMutation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MutationObserver, noop, shouldThrowError } from '@tanstack/query-core'
import { createComputed, createMemo, on, onCleanup } from 'solid-js'
import { createStore } from 'solid-js/store'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import type { DefaultError } from '@tanstack/query-core'
import type { QueryClient } from './QueryClient'
import type {
Expand All @@ -21,7 +21,8 @@ export function useMutation<
options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,
queryClient?: Accessor<QueryClient>,
): UseMutationResult<TData, TError, TVariables, TOnMutateResult> {
const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())

const observer = new MutationObserver<
TData,
Expand Down
5 changes: 3 additions & 2 deletions packages/solid-query/src/useMutationState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createEffect, createMemo, createSignal, onCleanup } from 'solid-js'
import { replaceEqualDeep } from '@tanstack/query-core'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import type {
Mutation,
MutationCache,
Expand Down Expand Up @@ -31,7 +31,8 @@ export function useMutationState<TResult = MutationState>(
options: Accessor<MutationStateOptions<TResult>> = () => ({}),
queryClient?: Accessor<QueryClient>,
): Accessor<Array<TResult>> {
const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())
const mutationCache = createMemo(() => client().getMutationCache())

const [result, setResult] = createSignal(
Expand Down
5 changes: 3 additions & 2 deletions packages/solid-query/src/useQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
onCleanup,
onMount,
} from 'solid-js'
import { useQueryClient } from './QueryClientProvider'
import { useQueryClientResolver } from './QueryClientProvider'
import { useIsRestoring } from './isRestoring'
import type { SolidQueryOptions, UseQueryResult } from './types'
import type { Accessor } from 'solid-js'
Expand Down Expand Up @@ -196,7 +196,8 @@ export function useQueries<
}>,
queryClient?: Accessor<QueryClient>,
): TCombinedResult {
const client = createMemo(() => useQueryClient(queryClient?.()))
const resolveClient = useQueryClientResolver(queryClient)
const client = createMemo(() => resolveClient())
const isRestoring = useIsRestoring()

const defaultedQueries = createMemo(() =>
Expand Down
Loading