Skip to content

Commit f86eb7e

Browse files
authored
feat(core): add client to queryFunctionContext (#8599)
* feat: add queryClient to queryFunctionContext * fix: remove queryClient exception closing over a queryClient should now error, as we pass the queryClient directly to the queryFunctionContext * fix: persister * refactor: keep private reference to cache * chore: fix tests * docs: QueryFunctionContext * refactor: derive from private member * refactor: name it `client` * refactor: let's go with client * chore: try skipping the cache * chore: re-enable caching and try to bust it by changing sharedGlobals lol
1 parent a507400 commit f86eb7e

File tree

13 files changed

+37
-40
lines changed

13 files changed

+37
-40
lines changed

docs/framework/react/guides/query-functions.md

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ function fetchTodoList({ queryKey }) {
100100
The `QueryFunctionContext` is the object passed to each query function. It consists of:
101101

102102
- `queryKey: QueryKey`: [Query Keys](../query-keys)
103+
- `client: QueryClient`: [QueryClient](../../../../reference/QueryClient)
103104
- `signal?: AbortSignal`
104105
- [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) instance provided by TanStack Query
105106
- Can be used for [Query Cancellation](../query-cancellation)

nx.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"sharedGlobals": [
99
"{workspaceRoot}/.nvmrc",
1010
"{workspaceRoot}/package.json",
11-
"{workspaceRoot}/scripts/getTsupConfig.js",
11+
"{workspaceRoot}/scripts/*.js",
1212
"{workspaceRoot}/tsconfig.json",
1313
"{workspaceRoot}/eslint.config.js"
1414
],

packages/angular-query-experimental/src/__tests__/inject-query.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ describe('injectQuery', () => {
325325
expect(spy).toHaveBeenCalledTimes(2)
326326
// should call queryFn with context containing the new queryKey
327327
expect(spy).toBeCalledWith({
328+
client: queryClient,
328329
meta: undefined,
329330
queryKey: ['key8'],
330331
signal: expect.anything(),

packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts

+1-19
Original file line numberDiff line numberDiff line change
@@ -354,24 +354,6 @@ ruleTester.run('exhaustive-deps', rule, {
354354
}
355355
`,
356356
},
357-
{
358-
name: 'should ignore references of the queryClient',
359-
code: `
360-
const CONST_VAL = 1
361-
function useHook() {
362-
const queryClient = useQueryClient()
363-
const queryClient2 = useQueryClient()
364-
useQuery({
365-
queryKey: ["foo"],
366-
queryFn: () => {
367-
doSomething(queryClient)
368-
queryClient.invalidateQueries()
369-
doSomethingSus(queryClient2)
370-
}
371-
});
372-
}
373-
`,
374-
},
375357
{
376358
name: 'query key with nullish coalescing operator',
377359
code: `
@@ -470,7 +452,7 @@ ruleTester.run('exhaustive-deps', rule, {
470452
queryKey: ['foo'],
471453
queryFn: () => Promise.resolve(EXTERNAL),
472454
}),
473-
};
455+
};
474456
`,
475457
},
476458
{

packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts

+1-12
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ export const ExhaustiveDepsUtils = {
2929
return (
3030
reference.identifier.name !== 'undefined' &&
3131
reference.identifier.parent.type !== AST_NODE_TYPES.NewExpression &&
32-
!ExhaustiveDepsUtils.isInstanceOfKind(reference.identifier.parent) &&
33-
!ExhaustiveDepsUtils.isQueryClientReference(reference)
32+
!ExhaustiveDepsUtils.isInstanceOfKind(reference.identifier.parent)
3433
)
3534
},
3635
isInstanceOfKind(node: TSESTree.Node) {
@@ -39,14 +38,4 @@ export const ExhaustiveDepsUtils = {
3938
node.operator === 'instanceof'
4039
)
4140
},
42-
isQueryClientReference(reference: TSESLint.Scope.Reference) {
43-
const declarator = reference.resolved?.defs[0]?.node
44-
45-
return (
46-
declarator?.type === AST_NODE_TYPES.VariableDeclarator &&
47-
declarator.init?.type === AST_NODE_TYPES.CallExpression &&
48-
declarator.init.callee.type === AST_NODE_TYPES.Identifier &&
49-
declarator.init.callee.name === 'useQueryClient'
50-
)
51-
},
5241
}

packages/query-core/src/__tests__/infiniteQueryBehavior.test.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ describe('InfiniteQueryBehavior', () => {
8888

8989
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
9090
queryKey: key,
91+
client: queryClient,
9192
pageParam: 1,
9293
meta: undefined,
9394
direction: 'forward',
@@ -101,6 +102,7 @@ describe('InfiniteQueryBehavior', () => {
101102

102103
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
103104
queryKey: key,
105+
client: queryClient,
104106
pageParam: 2,
105107
direction: 'forward',
106108
meta: undefined,
@@ -119,6 +121,7 @@ describe('InfiniteQueryBehavior', () => {
119121

120122
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
121123
queryKey: key,
124+
client: queryClient,
122125
pageParam: 0,
123126
direction: 'backward',
124127
meta: undefined,
@@ -138,6 +141,7 @@ describe('InfiniteQueryBehavior', () => {
138141

139142
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
140143
queryKey: key,
144+
client: queryClient,
141145
pageParam: -1,
142146
meta: undefined,
143147
direction: 'backward',
@@ -156,6 +160,7 @@ describe('InfiniteQueryBehavior', () => {
156160

157161
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
158162
queryKey: key,
163+
client: queryClient,
159164
pageParam: 1,
160165
meta: undefined,
161166
direction: 'forward',
@@ -177,6 +182,7 @@ describe('InfiniteQueryBehavior', () => {
177182

178183
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
179184
queryKey: key,
185+
client: queryClient,
180186
pageParam: 0,
181187
meta: undefined,
182188
direction: 'forward',
@@ -185,6 +191,7 @@ describe('InfiniteQueryBehavior', () => {
185191

186192
expect(queryFnSpy).toHaveBeenNthCalledWith(2, {
187193
queryKey: key,
194+
client: queryClient,
188195
pageParam: 1,
189196
meta: undefined,
190197
direction: 'forward',
@@ -237,6 +244,7 @@ describe('InfiniteQueryBehavior', () => {
237244

238245
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
239246
queryKey: key,
247+
client: queryClient,
240248
pageParam: 1,
241249
meta: undefined,
242250
direction: 'forward',
@@ -293,6 +301,7 @@ describe('InfiniteQueryBehavior', () => {
293301

294302
expect(queryFnSpy).toHaveBeenNthCalledWith(1, {
295303
queryKey: key,
304+
client: queryClient,
296305
pageParam: 2,
297306
meta: undefined,
298307
direction: 'forward',

packages/query-core/src/__tests__/query.test.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ describe('query', () => {
214214
expect(args.pageParam).toBeUndefined()
215215
expect(args.queryKey).toEqual(key)
216216
expect(args.signal).toBeInstanceOf(AbortSignal)
217+
expect(args.client).toEqual(queryClient)
217218
})
218219

219220
test('should continue if cancellation is not supported and signal is not consumed', async () => {

packages/query-core/src/__tests__/queryClient.test-d.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ describe('defaultOptions', () => {
184184
queries: {
185185
queryFn: (context) => {
186186
expectTypeOf(context).toEqualTypeOf<{
187+
client: QueryClient
187188
queryKey: QueryKey
188189
meta: Record<string, unknown> | undefined
189190
signal: AbortSignal

packages/query-core/src/infiniteQueryBehavior.ts

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function infiniteQueryBehavior<TQueryFnData, TError, TData, TPageParam>(
5858
QueryFunctionContext<QueryKey, unknown>,
5959
'signal'
6060
> = {
61+
client: context.client,
6162
queryKey: context.queryKey,
6263
pageParam: param,
6364
direction: previous ? 'backward' : 'forward',
@@ -114,6 +115,7 @@ export function infiniteQueryBehavior<TQueryFnData, TError, TData, TPageParam>(
114115
return context.options.persister?.(
115116
fetchFn as any,
116117
{
118+
client: context.client,
117119
queryKey: context.queryKey,
118120
meta: context.options.meta,
119121
signal: context.signal,

packages/query-core/src/query.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
import { notifyManager } from './notifyManager'
1010
import { canFetch, createRetryer, isCancelledError } from './retryer'
1111
import { Removable } from './removable'
12+
import type { QueryCache } from './queryCache'
13+
import type { QueryClient } from './queryClient'
1214
import type {
1315
CancelOptions,
1416
DefaultError,
@@ -23,7 +25,6 @@ import type {
2325
QueryStatus,
2426
SetDataOptions,
2527
} from './types'
26-
import type { QueryCache } from './queryCache'
2728
import type { QueryObserver } from './queryObserver'
2829
import type { Retryer } from './retryer'
2930

@@ -35,7 +36,7 @@ interface QueryConfig<
3536
TData,
3637
TQueryKey extends QueryKey = QueryKey,
3738
> {
38-
cache: QueryCache
39+
client: QueryClient
3940
queryKey: TQueryKey
4041
queryHash: string
4142
options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
@@ -68,6 +69,7 @@ export interface FetchContext<
6869
fetchOptions?: FetchOptions
6970
signal: AbortSignal
7071
options: QueryOptions<TQueryFnData, TError, TData, any>
72+
client: QueryClient
7173
queryKey: TQueryKey
7274
state: QueryState<TData, TError>
7375
}
@@ -167,6 +169,7 @@ export class Query<
167169
#initialState: QueryState<TData, TError>
168170
#revertState?: QueryState<TData, TError>
169171
#cache: QueryCache
172+
#client: QueryClient
170173
#retryer?: Retryer<TData>
171174
observers: Array<QueryObserver<any, any, any, any, any>>
172175
#defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
@@ -179,7 +182,8 @@ export class Query<
179182
this.#defaultOptions = config.defaultOptions
180183
this.setOptions(config.options)
181184
this.observers = []
182-
this.#cache = config.cache
185+
this.#client = config.client
186+
this.#cache = this.#client.getQueryCache()
183187
this.queryKey = config.queryKey
184188
this.queryHash = config.queryHash
185189
this.#initialState = getDefaultState(this.options)
@@ -411,6 +415,7 @@ export class Query<
411415
QueryFunctionContext<TQueryKey>,
412416
'signal'
413417
> = {
418+
client: this.#client,
414419
queryKey: this.queryKey,
415420
meta: this.meta,
416421
}
@@ -437,6 +442,7 @@ export class Query<
437442
fetchOptions,
438443
options: this.options,
439444
queryKey: this.queryKey,
445+
client: this.#client,
440446
state: this.state,
441447
fetchFn,
442448
}

packages/query-core/src/queryCache.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
117117

118118
if (!query) {
119119
query = new Query({
120-
cache: this,
120+
client,
121121
queryKey,
122122
queryHash,
123123
options: client.defaultQueryOptions(options),

packages/query-core/src/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* istanbul ignore file */
22

3+
import type { QueryClient } from './queryClient'
34
import type { DehydrateOptions, HydrateOptions } from './hydration'
45
import type { MutationState } from './mutation'
56
import type { FetchDirection, Query, QueryBehavior } from './query'
@@ -116,6 +117,7 @@ export type QueryFunctionContext<
116117
TPageParam = never,
117118
> = [TPageParam] extends [never]
118119
? {
120+
client: QueryClient
119121
queryKey: TQueryKey
120122
signal: AbortSignal
121123
meta: QueryMeta | undefined
@@ -127,6 +129,7 @@ export type QueryFunctionContext<
127129
direction?: unknown
128130
}
129131
: {
132+
client: QueryClient
130133
queryKey: TQueryKey
131134
signal: AbortSignal
132135
pageParam: TPageParam

packages/query-persist-client-core/src/__tests__/createPersister.test.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { describe, expect, test, vi } from 'vitest'
2-
import { Query, QueryCache, hashKey } from '@tanstack/query-core'
2+
import { Query, QueryClient, hashKey } from '@tanstack/query-core'
33
import {
44
PERSISTER_KEY_PREFIX,
55
experimental_createPersister,
66
} from '../createPersister'
77
import { sleep } from './utils'
8+
import type { QueryFunctionContext, QueryKey } from '@tanstack/query-core'
89
import type { StoragePersisterOptions } from '../createPersister'
9-
import type { QueryKey } from '@tanstack/query-core'
1010

1111
function getFreshStorage() {
1212
const storage = new Map()
@@ -25,12 +25,14 @@ function setupPersister(
2525
queryKey: QueryKey,
2626
persisterOptions: StoragePersisterOptions,
2727
) {
28+
const client = new QueryClient()
2829
const context = {
2930
meta: { foo: 'bar' },
31+
client,
3032
queryKey,
3133
// @ts-expect-error
3234
signal: undefined as AbortSignal,
33-
}
35+
} satisfies QueryFunctionContext
3436
const queryHash = hashKey(queryKey)
3537
const storageKey = `${PERSISTER_KEY_PREFIX}-${queryHash}`
3638

@@ -39,7 +41,7 @@ function setupPersister(
3941
const persisterFn = experimental_createPersister(persisterOptions)
4042

4143
const query = new Query({
42-
cache: new QueryCache(),
44+
client,
4345
queryHash,
4446
queryKey,
4547
})

0 commit comments

Comments
 (0)