Skip to content

Commit 61f4d74

Browse files
authored
refactor(types): make queryKey required on ObserverOptions (#6879)
* refactor(types): make queryKey required on ObserverOptions we cannot create an observer without a key, because an observer, per definition, watches a certain query by its key * test: observers need a key * chore: remove a branch that can't exist we can't have an observer without a queryKey * fix: when comparing with shallowEqualObjects, the currentResult must come first because it doesn't detect length changes * test: we get another event * types: you can't set queryKey as default * a test for undefined queryKey makes no sense * fix: more type issues * types: queryKey is also not required for defaultOptions in solid * fix(core): shallowEqualObjects should return false for objects with different lengths as we use it for options, and the length of options can change
1 parent 7595412 commit 61f4d74

File tree

22 files changed

+127
-141
lines changed

22 files changed

+127
-141
lines changed

docs/reference/QueryCache.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ const query = queryCache.find(queryKey)
6363

6464
**Options**
6565

66-
- `queryKey?: QueryKey`: [Query Keys](./framework/react/guides/query-keys)
6766
- `filters?: QueryFilters`: [Query Filters](./framework/react/guides/filters#query-filters)
6867

6968
**Returns**

packages/angular-query-experimental/src/types.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
QueryKey,
1313
QueryObserverOptions,
1414
QueryObserverResult,
15-
WithRequired,
1615
} from '@tanstack/query-core'
1716
import type { MapToSignals } from './signal-proxy'
1817

@@ -22,9 +21,12 @@ export interface CreateBaseQueryOptions<
2221
TData = TQueryFnData,
2322
TQueryData = TQueryFnData,
2423
TQueryKey extends QueryKey = QueryKey,
25-
> extends WithRequired<
26-
QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
27-
'queryKey'
24+
> extends QueryObserverOptions<
25+
TQueryFnData,
26+
TError,
27+
TData,
28+
TQueryData,
29+
TQueryKey
2830
> {}
2931

3032
export interface CreateQueryOptions<
@@ -33,15 +35,12 @@ export interface CreateQueryOptions<
3335
TData = TQueryFnData,
3436
TQueryKey extends QueryKey = QueryKey,
3537
> extends Omit<
36-
WithRequired<
37-
CreateBaseQueryOptions<
38-
TQueryFnData,
39-
TError,
40-
TData,
41-
TQueryFnData,
42-
TQueryKey
43-
>,
44-
'queryKey'
38+
CreateBaseQueryOptions<
39+
TQueryFnData,
40+
TError,
41+
TData,
42+
TQueryFnData,
43+
TQueryKey
4544
>,
4645
'suspense'
4746
> {}
@@ -83,19 +82,16 @@ export interface CreateInfiniteQueryOptions<
8382
TQueryData = TQueryFnData,
8483
TQueryKey extends QueryKey = QueryKey,
8584
TPageParam = unknown,
86-
> extends WithRequired<
87-
Omit<
88-
InfiniteQueryObserverOptions<
89-
TQueryFnData,
90-
TError,
91-
TData,
92-
TQueryData,
93-
TQueryKey,
94-
TPageParam
95-
>,
96-
'suspense'
85+
> extends Omit<
86+
InfiniteQueryObserverOptions<
87+
TQueryFnData,
88+
TError,
89+
TData,
90+
TQueryData,
91+
TQueryKey,
92+
TPageParam
9793
>,
98-
'queryKey'
94+
'suspense'
9995
> {}
10096

10197
export type CreateBaseQueryResult<

packages/query-core/src/infiniteQueryObserver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export class InfiniteQueryObserver<
7070
}
7171

7272
setOptions(
73-
options?: InfiniteQueryObserverOptions<
73+
options: InfiniteQueryObserverOptions<
7474
TQueryFnData,
7575
TError,
7676
TData,

packages/query-core/src/mutationObserver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class MutationObserver<
5959
| MutationObserverOptions<TData, TError, TVariables, TContext>
6060
| undefined
6161
this.options = this.#client.defaultMutationOptions(options)
62-
if (!shallowEqualObjects(prevOptions, this.options)) {
62+
if (!shallowEqualObjects(this.options, prevOptions)) {
6363
this.#client.getMutationCache().notify({
6464
type: 'observerOptionsUpdated',
6565
mutation: this.#currentMutation,

packages/query-core/src/queryCache.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
9999

100100
build<TQueryFnData, TError, TData, TQueryKey extends QueryKey>(
101101
client: QueryClient,
102-
options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,
102+
options: WithRequired<
103+
QueryOptions<TQueryFnData, TError, TData, TQueryKey>,
104+
'queryKey'
105+
>,
103106
state?: QueryState<TData, TError>,
104107
): Query<TQueryFnData, TError, TData, TQueryKey> {
105-
const queryKey = options.queryKey!
108+
const queryKey = options.queryKey
106109
const queryHash =
107110
options.queryHash ?? hashQueryKeyByOptions(queryKey, options)
108111
let query = this.get<TQueryFnData, TError, TData, TQueryKey>(queryHash)

packages/query-core/src/queryClient.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import type { MutationFilters, QueryFilters, Updater } from './utils'
4141

4242
interface QueryDefaults {
4343
queryKey: QueryKey
44-
defaultOptions: QueryOptions<any, any, any>
44+
defaultOptions: Omit<QueryOptions<any, any, any>, 'queryKey'>
4545
}
4646

4747
interface MutationDefaults {
@@ -409,10 +409,13 @@ export class QueryClient {
409409

410410
getQueryDefaults(
411411
queryKey: QueryKey,
412-
): QueryObserverOptions<any, any, any, any, any> {
412+
): Omit<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> {
413413
const defaults = [...this.#queryDefaults.values()]
414414

415-
let result: QueryObserverOptions<any, any, any, any, any> = {}
415+
let result: Omit<
416+
QueryObserverOptions<any, any, any, any, any>,
417+
'queryKey'
418+
> = {}
416419

417420
defaults.forEach((queryDefault) => {
418421
if (partialMatchKey(queryKey, queryDefault.queryKey)) {
@@ -456,7 +459,7 @@ export class QueryClient {
456459
TQueryKey extends QueryKey = QueryKey,
457460
TPageParam = never,
458461
>(
459-
options?:
462+
options:
460463
| QueryObserverOptions<
461464
TQueryFnData,
462465
TError,
@@ -479,7 +482,7 @@ export class QueryClient {
479482
TQueryData,
480483
TQueryKey
481484
> {
482-
if (options?._defaulted) {
485+
if (options._defaulted) {
483486
return options as DefaultedQueryObserverOptions<
484487
TQueryFnData,
485488
TError,
@@ -491,7 +494,7 @@ export class QueryClient {
491494

492495
const defaultedOptions = {
493496
...this.#defaultOptions.queries,
494-
...(options?.queryKey && this.getQueryDefaults(options.queryKey)),
497+
...this.getQueryDefaults(options.queryKey),
495498
...options,
496499
_defaulted: true,
497500
}

packages/query-core/src/queryObserver.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class QueryObserver<
132132
}
133133

134134
setOptions(
135-
options?: QueryObserverOptions<
135+
options: QueryObserverOptions<
136136
TQueryFnData,
137137
TError,
138138
TData,
@@ -146,7 +146,7 @@ export class QueryObserver<
146146

147147
this.options = this.#client.defaultQueryOptions(options)
148148

149-
if (!shallowEqualObjects(prevOptions, this.options)) {
149+
if (!shallowEqualObjects(this.options, prevOptions)) {
150150
this.#client.getQueryCache().notify({
151151
type: 'observerOptionsUpdated',
152152
query: this.#currentQuery,
@@ -161,11 +161,6 @@ export class QueryObserver<
161161
throw new Error('Expected enabled to be a boolean')
162162
}
163163

164-
// Keep previous query key if the user does not supply one
165-
if (!this.options.queryKey) {
166-
this.options.queryKey = prevOptions.queryKey
167-
}
168-
169164
this.#updateQuery()
170165

171166
const mounted = this.hasListeners()

packages/query-core/src/tests/queriesObserver.test.tsx

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,6 @@ describe('queriesObserver', () => {
3434
expect(observerResult).toMatchObject([{ data: 1 }, { data: 2 }])
3535
})
3636

37-
test('should still return value for undefined query key', async () => {
38-
const consoleMock = vi.spyOn(console, 'error')
39-
consoleMock.mockImplementation(() => undefined)
40-
const key1 = queryKey()
41-
const queryFn1 = vi.fn().mockReturnValue(1)
42-
const queryFn2 = vi.fn().mockReturnValue(2)
43-
const observer = new QueriesObserver(queryClient, [
44-
{ queryKey: key1, queryFn: queryFn1 },
45-
{ queryKey: undefined, queryFn: queryFn2 },
46-
])
47-
let observerResult
48-
const unsubscribe = observer.subscribe((result) => {
49-
observerResult = result
50-
})
51-
await sleep(1)
52-
unsubscribe()
53-
expect(observerResult).toMatchObject([{ data: 1 }, { data: 2 }])
54-
55-
expect(consoleMock).toHaveBeenCalledTimes(1)
56-
expect(consoleMock).toHaveBeenCalledWith(
57-
"As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']",
58-
)
59-
consoleMock.mockRestore()
60-
})
61-
6237
test('should update when a query updates', async () => {
6338
const key1 = queryKey()
6439
const key2 = queryKey()

packages/query-core/src/tests/queryCache.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,11 @@ describe('queryCache', () => {
5353
const unsubScribeObserver = observer.subscribe(vi.fn())
5454

5555
await waitFor(() => {
56-
expect(events.length).toBe(8)
56+
expect(events.length).toBe(9)
5757
})
5858

5959
expect(events).toEqual([
60+
'observerOptionsUpdated',
6061
'added', // 1. Query added -> loading
6162
'observerResultsUpdated', // 2. Observer result updated -> loading
6263
'observerAdded', // 3. Observer added

packages/query-core/src/tests/queryObserver.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ describe('queryObserver', () => {
459459
const unsubscribe = observer.subscribe((x) => {
460460
results.push(x)
461461
})
462-
observer.setOptions({ enabled: false, staleTime: 10 })
462+
observer.setOptions({ queryKey: key, enabled: false, staleTime: 10 })
463463
await queryClient.fetchQuery({ queryKey: key, queryFn })
464464
await sleep(100)
465465
unsubscribe()
@@ -579,7 +579,7 @@ describe('queryObserver', () => {
579579

580580
const firstData = observer.getCurrentResult().data
581581

582-
observer.setOptions({ placeholderData: {} })
582+
observer.setOptions({ queryKey: key, placeholderData: {} })
583583

584584
const secondData = observer.getCurrentResult().data
585585

@@ -885,7 +885,7 @@ describe('queryObserver', () => {
885885

886886
const spy = vi.fn()
887887
const unsubscribe = queryClient.getQueryCache().subscribe(spy)
888-
observer.setOptions({ enabled: false })
888+
observer.setOptions({ queryKey: key, enabled: false })
889889

890890
expect(spy).toHaveBeenCalledTimes(1)
891891
expect(spy).toHaveBeenCalledWith(

0 commit comments

Comments
 (0)