Skip to content

Commit 149a043

Browse files
committed
Merge commit '118801df342881021c2bb6c8add5bb11b6dd944a' into alpha
# Conflicts: # packages/query-async-storage-persister/package.json # packages/query-broadcast-client-experimental/package.json # packages/query-core/package.json # packages/query-core/src/queryObserver.ts # packages/query-persist-client-core/package.json # packages/query-sync-storage-persister/package.json # packages/react-query-devtools/package.json # packages/react-query-persist-client/package.json # packages/react-query/package.json # packages/react-query/src/__tests__/useQuery.test.tsx # packages/solid-query/package.json # packages/svelte-query/package.json # packages/vue-query/package.json
2 parents b7e548b + 118801d commit 149a043

File tree

9 files changed

+329
-93
lines changed

9 files changed

+329
-93
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Still on **React Query v3**? No problem! Check out the v3 docs here: https://tan
4343
- Paginated + Cursor-based Queries
4444
- Load-More + Infinite Scroll Queries w/ Scroll Recovery
4545
- Request Cancellation
46-
- [React Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html) + Fetch-As-You-Render Query Prefetching
46+
- [React Suspense](https://react.dev/reference/react/Suspense) + Fetch-As-You-Render Query Prefetching
4747
- Dedicated Devtools
4848
- <a href="https://bundlephobia.com/package/@tanstack/react-query@latest" target="\_parent">
4949
<img alt="" src="https://badgen.net/bundlephobia/minzip/@tanstack/react-query" />

docs/react/guides/query-keys.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ function Todos({ todoId }) {
9191

9292
[//]: # 'Example5'
9393

94-
Note that query keys act as dependencies for your query functions. Adding dependent variables to your query key will ensure that queries are cached independently, and that any time a variable changes, *queries will be refetched automatically (depending on your `staleTime` settings).* (See the [exhaustive-deps](../eslint/exhaustive-deps) section for more information and examples.)
94+
Note that query keys act as dependencies for your query functions. Adding dependent variables to your query key will ensure that queries are cached independently, and that any time a variable changes, *queries will be refetched automatically* (depending on your `staleTime` settings). See the [exhaustive-deps](../eslint/exhaustive-deps) section for more information and examples.
95+
9596
[//]: # 'Materials'
9697

9798
## Further reading

docs/react/overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function Example() {
6969
const { isPending, error, data } = useQuery({
7070
queryKey: ['repoData'],
7171
queryFn: () =>
72-
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(
72+
fetch('https://api.github.com/repos/TanStack/query').then(
7373
(res) => res.json(),
7474
),
7575
})

docs/react/react-native.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,64 @@ export function useRefreshOnFocus<T>(refetch: () => Promise<T>) {
7676
```
7777

7878
In the above code, `refetch` is skipped the first time because `useFocusEffect` calls our callback on mount in addition to screen focus.
79+
80+
## Disable re-renders on out of focus Screens
81+
82+
In some situations, including performance concerns, you may want to stop re-renders when a React Native screen gets out of focus. To achieve this we can use `useFocusEffect` from `@react-navigation/native` together with the `notifyOnChangeProps` query option.
83+
84+
This custom hook provides a `notifyOnChangeProps` option that will return an empty array whenever a screen goes out of focus - effectively stopping any re-renders on that scenario. Whenever the screens gets in focus again, the behavior goes back to normal.
85+
86+
```tsx
87+
import React from 'react'
88+
import { NotifyOnChangeProps } from '@tanstack/query-core'
89+
import { useFocusEffect } from '@react-navigation/native'
90+
91+
export function useFocusNotifyOnChangeProps(notifyOnChangeProps?: NotifyOnChangeProps) {
92+
const focusedRef = React.useRef(true)
93+
94+
useFocusEffect(
95+
React.useCallback(() => {
96+
focusedRef.current = true
97+
98+
return () => {
99+
focusedRef.current = false
100+
}
101+
}, [])
102+
)
103+
104+
return () => {
105+
if (!focusedRef.current) {
106+
return []
107+
}
108+
109+
if (typeof notifyOnChangeProps === 'function') {
110+
return notifyOnChangeProps()
111+
}
112+
113+
return notifyOnChangeProps.current
114+
}
115+
}
116+
```
117+
118+
In the above code, `useFocusEffect` is used to change the value of a reference that the callback will use as a condition.
119+
120+
The argument is wrapped in a reference to also guarantee that the returned callback always keeps the same reference.
121+
122+
Example usage:
123+
124+
```tsx
125+
function MyComponent() {
126+
const notifyOnChangeProps = useFocusNotifyOnChangeProps();
127+
128+
const { dataUpdatedAt } = useQuery({
129+
queryKey: ['myKey'],
130+
queryFn: async () => {
131+
const response = await fetch('https://api.github.com/repos/tannerlinsley/react-query');
132+
return response.json();
133+
},
134+
notifyOnChangeProps,
135+
});
136+
137+
return <div>DataUpdatedAt: {dataUpdatedAt}</div>;
138+
};
139+
```

docs/react/reference/useQuery.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,12 @@ const {
125125
- If set to `false`, the query will not refetch on reconnect.
126126
- If set to `"always"`, the query will always refetch on reconnect.
127127
- If set to a function, the function will be executed with the query to compute the value
128-
- `notifyOnChangeProps: string[] | "all"`
128+
- `notifyOnChangeProps: string[] | "all" | (() => string[] | "all")`
129129
- Optional
130130
- If set, the component will only re-render if any of the listed properties change.
131131
- If set to `['data', 'error']` for example, the component will only re-render when the `data` or `error` properties change.
132132
- If set to `"all"`, the component will opt-out of smart tracking and re-render whenever a query is updated.
133+
- If set to a function, the function will be executed to compute the list of properties.
133134
- By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change.
134135
- `select: (data: TData) => unknown`
135136
- Optional

packages/query-core/src/queryObserver.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,15 +612,19 @@ export class QueryObserver<
612612
}
613613

614614
const { notifyOnChangeProps } = this.options
615+
const notifyOnChangePropsValue =
616+
typeof notifyOnChangeProps === 'function'
617+
? notifyOnChangeProps()
618+
: notifyOnChangeProps
615619

616620
if (
617-
notifyOnChangeProps === 'all' ||
618-
(!notifyOnChangeProps && !this.#trackedProps.size)
621+
notifyOnChangePropsValue === 'all' ||
622+
(!notifyOnChangePropsValue && !this.#trackedProps.size)
619623
) {
620624
return true
621625
}
622626

623-
const includedProps = new Set(notifyOnChangeProps ?? this.#trackedProps)
627+
const includedProps = new Set(notifyOnChangePropsValue ?? this.#trackedProps)
624628

625629
if (this.options.throwOnError) {
626630
includedProps.add('error')

packages/query-core/src/types.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ export type QueryMeta = Register extends {
9595

9696
export type NetworkMode = 'online' | 'always' | 'offlineFirst'
9797

98+
export type NotifyOnChangeProps =
99+
| Array<keyof InfiniteQueryObserverResult>
100+
| 'all'
101+
| (() => Array<keyof InfiniteQueryObserverResult> | 'all')
102+
98103
export interface QueryOptions<
99104
TQueryFnData = unknown,
100105
TError = DefaultError,
@@ -261,9 +266,10 @@ export interface QueryObserverOptions<
261266
* If set, the component will only re-render if any of the listed properties change.
262267
* When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change.
263268
* When set to `'all'`, the component will re-render whenever a query is updated.
269+
* When set to a function, the function will be executed to compute the list of properties.
264270
* By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change.
265271
*/
266-
notifyOnChangeProps?: Array<keyof InfiniteQueryObserverResult> | 'all'
272+
notifyOnChangeProps?: NotifyOnChangeProps
267273
/**
268274
* Whether errors should be thrown instead of setting the `error` property.
269275
* If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary.
@@ -292,8 +298,8 @@ export interface QueryObserverOptions<
292298
_optimisticResults?: 'optimistic' | 'isRestoring'
293299
}
294300

295-
export type WithRequired<T, K extends keyof T> = Omit<T, K> &
296-
Required<Pick<T, K>>
301+
export type WithRequired<T, K extends keyof T> = T & { [_ in K]: {} }
302+
297303
export type DefaultedQueryObserverOptions<
298304
TQueryFnData = unknown,
299305
TError = DefaultError,

0 commit comments

Comments
 (0)