Skip to content

Commit 85d458d

Browse files
committed
chore(query core): upgrade version
1 parent 99dd36d commit 85d458d

File tree

6 files changed

+104
-29
lines changed

6 files changed

+104
-29
lines changed

docs/src/pages/comparison.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Feature/Capability Key:
5353

5454
> **<sup>1</sup> Lagged Query Data** - Svelte Query provides a way to continue to see an existing query's data while the next query loads (similar to the same UX that suspense will soon provide natively). This is extremely important when writing pagination UIs or infinite loading UIs where you do not want to show a hard loading state whenever a new query is requested. Other libraries do not have this capability and render a hard loading state for the new query (unless it has been prefetched), while the new query loads.
5555
56-
> **<sup>2</sup> Render Optimization** - Svelte Query has excellent rendering performance. It will only re-render your components when a query is updated. For example because it has new data, or to indicate it is fetching. Svelte Query also batches updates together to make sure your application only re-renders once when multiple components are using the same query. If you are only interested in the `data` or `error` properties, you can reduce the number of renders even more by setting `notifyOnStatusChange` to `false`.
56+
> **<sup>2</sup> Render Optimization** - Svelte Query has excellent rendering performance. It will only re-render your components when a query is updated. For example because it has new data, or to indicate it is fetching. Svelte Query also batches updates together to make sure your application only re-renders once when multiple components are using the same query. If you are only interested in the `data` or `error` properties, you can reduce the number of renders even more by setting `notifyOnChangeProps` to `['data', 'error']`.
5757
5858
> **<sup>3</sup> Partial query matching** - Because Svelte Query uses deterministic query key serialization, this allows you to manipulate variable groups of queries without having to know each individual query-key that you want to match, eg. you can refetch every query that starts with `todos` in its key, regardless of variables, or you can target specific queries with (or without) variables or nested properties, and even use a filter function to only match queries that pass your specific conditions.
5959

docs/src/pages/graphql.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ Because Svelte Query's fetching mechanisms are agnostically built on Promises, y
99
1010
## Examples
1111

12-
- [basic-graphql-request](../docs/examples/basic-graphql-request) (The "basic" example, but implemented with [`graphq-request`](https://github.com/prisma-labs/graphql-request))
12+
- [basic-graphql-request](../docs/examples/basic-graphql-request) (The "basic" example, but implemented with [`graphql-request`](https://github.com/prisma-labs/graphql-request))

docs/src/pages/reference/useQuery.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ const queryResult = useQuery(queryKey, queryFn?, {
1010
initialData,
1111
isDataEqual,
1212
keepPreviousData,
13-
notifyOnFetchChange,
14-
notifyOnStaleChange,
15-
notifyOnStatusChange,
13+
notifyOnChangeProps,
14+
notifyOnChangePropsExclusions,
1615
onError,
1716
onSettled,
1817
onSuccess,
@@ -111,14 +110,14 @@ const result = useQuery({
111110
- If set to `true`, the query will refetch on reconnect if the data is stale.
112111
- If set to `false`, the query will not refetch on reconnect.
113112
- If set to `"always"`, the query will always refetch on reconnect.
114-
- `notifyOnStaleChange: boolean`
113+
- `notifyOnChangeProps: string[]`
115114
- Optional
116-
- Set this to `true` to re-render when the `isStale` property changes.
117-
- Defaults to `false`.
118-
- `notifyOnStatusChange: boolean`
115+
- If set, the component will only re-render if any of the listed properties change.
116+
- If set to `['data', 'error']` for example, the component will only re-render when the `data` or `error` properties change.
117+
- `notifyOnChangePropsExclusions: string[]`
119118
- Optional
120-
- Set this to `false` to only re-render when there are changes to `data` or `error`.
121-
- Defaults to `true`.
119+
- If set, the component will not re-render if any of the listed properties change.
120+
- If set to `['isStale']` for example, the component will not re-render when the `isStale` property changes.
122121
- `onSuccess: (data: TData) => void`
123122
- Optional
124123
- This function will fire any time the query successfully fetches new data.

docs/src/pages/videos.mdx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,48 @@ title: Videos & Talks
1616
></iframe>
1717

1818
[Click here to view the Repository used for the above presentation](https://github.com/TanStack/svelte-query-blog-refactor-example)
19+
20+
<iframe
21+
width="280"
22+
height="400"
23+
src="https://www.youtube.com/embed/DocXo3gqGdI"
24+
frameborder="0"
25+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
26+
allowfullscreen
27+
style={{
28+
width: '100%',
29+
}}
30+
></iframe>
31+
<iframe
32+
width="280"
33+
height="400"
34+
src="https://www.youtube.com/embed/PPvWXbSCtBU"
35+
frameborder="0"
36+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
37+
allowfullscreen
38+
style={{
39+
width: '100%',
40+
}}
41+
></iframe>
42+
<iframe
43+
width="280"
44+
height="400"
45+
src="https://www.youtube.com/embed/B3cJDT3j19I"
46+
frameborder="0"
47+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
48+
allowfullscreen
49+
style={{
50+
width: '100%',
51+
}}
52+
></iframe>
53+
<iframe
54+
width="280"
55+
height="400"
56+
src="https://www.youtube.com/embed/_ehibado6rU"
57+
frameborder="0"
58+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
59+
allowfullscreen
60+
style={{
61+
width: '100%',
62+
}}
63+
></iframe>

src/queryCore/core/queryObserver.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class QueryObserver<
4242
TError = unknown,
4343
TQueryFnData = TData,
4444
TQueryData = TQueryFnData
45-
> extends Subscribable<QueryObserverListener<TData, TError>> {
45+
> extends Subscribable<QueryObserverListener<TData, TError>> {
4646
options: QueryObserverOptions<TData, TError, TQueryFnData, TQueryData>
4747

4848
private client: QueryClient
@@ -288,9 +288,10 @@ export class QueryObserver<
288288
// @ts-ignore
289289
this.staleTimeoutId = setTimeout(() => {
290290
if (!this.currentResult.isStale) {
291+
const prevResult = this.currentResult
291292
this.updateResult()
292293
this.notify({
293-
listeners: this.options.notifyOnStaleChange === true,
294+
listeners: this.shouldNotifyListeners(prevResult, this.currentResult),
294295
cache: true,
295296
})
296297
}
@@ -329,7 +330,7 @@ export class QueryObserver<
329330
}
330331

331332
private clearStaleTimeout(): void {
332-
clearInterval(this.staleTimeoutId)
333+
clearTimeout(this.staleTimeoutId)
333334
this.staleTimeoutId = undefined
334335
}
335336

@@ -423,6 +424,42 @@ export class QueryObserver<
423424
return result as QueryObserverResult<TData, TError>
424425
}
425426

427+
private shouldNotifyListeners(
428+
prevResult: QueryObserverResult,
429+
result: QueryObserverResult
430+
): boolean {
431+
const { notifyOnChangeProps, notifyOnChangePropsExclusions } = this.options
432+
433+
if (prevResult === result) {
434+
return false
435+
}
436+
437+
if (!notifyOnChangeProps && !notifyOnChangePropsExclusions) {
438+
return true
439+
}
440+
441+
const keys = Object.keys(result)
442+
443+
for (let i = 0; i < keys.length; i++) {
444+
const key = keys[i] as keyof QueryObserverResult
445+
const changed = prevResult[key] !== result[key]
446+
const isIncluded = notifyOnChangeProps?.some(x => x === key)
447+
const isExcluded = notifyOnChangePropsExclusions?.some(x => x === key)
448+
449+
if (changed) {
450+
if (notifyOnChangePropsExclusions && isExcluded) {
451+
continue
452+
}
453+
454+
if (!notifyOnChangeProps || isIncluded) {
455+
return true
456+
}
457+
}
458+
}
459+
460+
return false
461+
}
462+
426463
private updateResult(willFetch?: boolean): void {
427464
const result = this.getNewResult(willFetch)
428465

@@ -466,7 +503,9 @@ export class QueryObserver<
466503
prevQuery?.removeObserver(this)
467504
this.currentQuery.addObserver(this)
468505

469-
if (this.options.notifyOnStatusChange !== false) {
506+
if (
507+
this.shouldNotifyListeners(this.previousQueryResult, this.currentResult)
508+
) {
470509
this.notify({ listeners: true })
471510
}
472511
}
@@ -494,13 +533,7 @@ export class QueryObserver<
494533
notifyOptions.onError = true
495534
}
496535

497-
if (
498-
// Always notify if notifyOnStatusChange is set
499-
this.options.notifyOnStatusChange !== false ||
500-
// Otherwise only notify on data or error change
501-
currentResult.data !== prevResult.data ||
502-
currentResult.error !== prevResult.error
503-
) {
536+
if (this.shouldNotifyListeners(prevResult, currentResult)) {
504537
notifyOptions.listeners = true
505538
}
506539

src/queryCore/core/types.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,14 @@ export interface QueryObserverOptions<
128128
*/
129129
refetchOnMount?: boolean | 'always'
130130
/**
131-
* Whether a component should re-render when the `isStale` property changes.
132-
* Defaults to `false`.
131+
* If set, the component will only re-render if any of the listed properties change.
132+
* When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change.
133133
*/
134-
notifyOnStaleChange?: boolean
134+
notifyOnChangeProps?: Array<keyof InfiniteQueryObserverResult>
135135
/**
136-
* Whether a change to the query status should re-render a component.
137-
* If set to `false`, the component will only re-render when the actual `data` or `error` changes.
138-
* Defaults to `true`.
136+
* If set, the component will not re-render if any of the listed properties change.
139137
*/
140-
notifyOnStatusChange?: boolean
138+
notifyOnChangePropsExclusions?: Array<keyof InfiniteQueryObserverResult>
141139
/**
142140
* This callback will fire any time the query successfully fetches new data.
143141
*/

0 commit comments

Comments
 (0)