From 66bf3ecdb92243acedacc22640761ac18c13b957 Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Wed, 17 Nov 2021 22:40:22 -0500 Subject: [PATCH 01/11] feat(Query Options): remove notifyOnChangePropsExclusion - remove related code from queryObserver - remove type def - remove related tests --- src/core/queryObserver.ts | 7 ++- src/core/types.ts | 4 -- src/react/tests/useQuery.test.tsx | 71 ------------------------------- 3 files changed, 3 insertions(+), 79 deletions(-) diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index fe9cba01aa..d076963059 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -596,9 +596,9 @@ export class QueryObserver< return true } - const { notifyOnChangeProps, notifyOnChangePropsExclusions } = this.options + const { notifyOnChangeProps } = this.options - if (!notifyOnChangeProps && !notifyOnChangePropsExclusions) { + if (!notifyOnChangeProps) { return true } @@ -615,8 +615,7 @@ export class QueryObserver< const typedKey = key as keyof QueryObserverResult const changed = result[typedKey] !== prevResult[typedKey] const isIncluded = includedProps?.some(x => x === key) - const isExcluded = notifyOnChangePropsExclusions?.some(x => x === key) - return changed && !isExcluded && (!includedProps || isIncluded) + return changed && (!includedProps || isIncluded) }) } diff --git a/src/core/types.ts b/src/core/types.ts index 7d186fa1e4..8906ed7ddb 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -161,10 +161,6 @@ export interface QueryObserverOptions< * When set to `tracked`, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. */ notifyOnChangeProps?: Array | 'tracked' - /** - * If set, the component will not re-render if any of the listed properties change. - */ - notifyOnChangePropsExclusions?: Array /** * This callback will fire any time the query successfully fetches new data or the cache is updated via `setQueryData`. */ diff --git a/src/react/tests/useQuery.test.tsx b/src/react/tests/useQuery.test.tsx index c0a9a77584..ca117ecf94 100644 --- a/src/react/tests/useQuery.test.tsx +++ b/src/react/tests/useQuery.test.tsx @@ -917,46 +917,6 @@ describe('useQuery', () => { consoleMock.mockRestore() }) - it('should re-render when dataUpdatedAt changes but data remains the same', async () => { - const key = queryKey() - const states: UseQueryResult[] = [] - - function Page() { - const state = useQuery(key, () => 'test', { - notifyOnChangePropsExclusions: [ - 'data', - 'isFetching', - 'isLoading', - 'isRefetching', - 'isSuccess', - 'status', - ], - }) - - states.push(state) - - const { refetch } = state - - React.useEffect(() => { - setActTimeout(() => { - refetch() - }, 5) - }, [refetch]) - - return null - } - - renderWithClient(queryClient, ) - - await sleep(10) - - expect(states.length).toBe(3) - expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) - expect(states[1]).toMatchObject({ data: 'test', isFetching: false }) - expect(states[2]).toMatchObject({ data: 'test', isFetching: false }) - expect(states[1]?.dataUpdatedAt).not.toBe(states[2]?.dataUpdatedAt) - }) - it('should track properties and only re-render when a tracked property changes', async () => { const key = queryKey() const states: UseQueryResult[] = [] @@ -992,37 +952,6 @@ describe('useQuery', () => { expect(states[1]).toMatchObject({ data: 'test' }) }) - it('should not re-render if a tracked prop changes, but it was excluded', async () => { - const key = queryKey() - const states: UseQueryResult[] = [] - - function Page() { - const state = useQuery(key, () => 'test', { - notifyOnChangeProps: 'tracked', - notifyOnChangePropsExclusions: ['data'], - }) - - states.push(state) - - return ( -
-

{state.data ?? 'null'}

-
- ) - } - - const rendered = renderWithClient(queryClient, ) - - await waitFor(() => rendered.getByText('null')) - expect(states.length).toBe(1) - expect(states[0]).toMatchObject({ data: undefined }) - - await queryClient.refetchQueries(key) - await waitFor(() => rendered.getByText('null')) - expect(states.length).toBe(1) - expect(states[0]).toMatchObject({ data: undefined }) - }) - it('should always re-render if we are tracking props but not using any', async () => { const key = queryKey() let renderCount = 0 From 3b2af749ab8b6c7cf8ece304ca965e0d1630ab2d Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 12:57:38 -0500 Subject: [PATCH 02/11] docs(Query Options): update notifyOnChangePropsExclusion sections - remove from api references - add to v4 migration guide --- docs/src/pages/guides/migrating-to-react-query-4.md | 4 ++++ docs/src/pages/reference/QueryClient.md | 2 +- docs/src/pages/reference/useQuery.md | 5 ----- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/src/pages/guides/migrating-to-react-query-4.md b/docs/src/pages/guides/migrating-to-react-query-4.md index c3ec75d6cb..f3c3ea3505 100644 --- a/docs/src/pages/guides/migrating-to-react-query-4.md +++ b/docs/src/pages/guides/migrating-to-react-query-4.md @@ -14,6 +14,10 @@ With version [3.22.0](https://github.com/tannerlinsley/react-query/releases/tag/ + import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query' ``` +### `notifyOnChangePropsExclusion` has been removed + +In v4, `notifyOnChangeProps` defaults to the `"tracked"` behavior of v3 instead of `undefined`. Now that `"tracked"` is the default behavior for v4, it no longer makes sense to include this config option. + ### Consistent behavior for `cancelRefetch` The `cancelRefetch` can be passed to all functions that imperatively fetch a query, namely: diff --git a/docs/src/pages/reference/QueryClient.md b/docs/src/pages/reference/QueryClient.md index 42f29eadaf..757d7244ae 100644 --- a/docs/src/pages/reference/QueryClient.md +++ b/docs/src/pages/reference/QueryClient.md @@ -91,7 +91,7 @@ try { **Options** -The options for `fetchQuery` are exactly the same as those of [`useQuery`](./useQuery), except the following: `enabled, refetchInterval, refetchIntervalInBackground, refetchOnWindowFocus, refetchOnReconnect, notifyOnChangeProps, notifyOnChangePropsExclusions, onSuccess, onError, onSettled, useErrorBoundary, select, suspense, keepPreviousData, placeholderData`; which are strictly for useQuery and useInfiniteQuery. You can check the [source code](https://github.com/tannerlinsley/react-query/blob/361935a12cec6f36d0bd6ba12e84136c405047c5/src/core/types.ts#L83) for more clarity. +The options for `fetchQuery` are exactly the same as those of [`useQuery`](./useQuery), except the following: `enabled, refetchInterval, refetchIntervalInBackground, refetchOnWindowFocus, refetchOnReconnect, notifyOnChangeProps, onSuccess, onError, onSettled, useErrorBoundary, select, suspense, keepPreviousData, placeholderData`; which are strictly for useQuery and useInfiniteQuery. You can check the [source code](https://github.com/tannerlinsley/react-query/blob/361935a12cec6f36d0bd6ba12e84136c405047c5/src/core/types.ts#L83) for more clarity. **Returns** diff --git a/docs/src/pages/reference/useQuery.md b/docs/src/pages/reference/useQuery.md index a2464cd2b7..757fda773f 100644 --- a/docs/src/pages/reference/useQuery.md +++ b/docs/src/pages/reference/useQuery.md @@ -35,7 +35,6 @@ const { keepPreviousData, meta, notifyOnChangeProps, - notifyOnChangePropsExclusions, onError, onSettled, onSuccess, @@ -131,10 +130,6 @@ const result = useQuery({ - If set, the component will only re-render if any of the listed properties change. - If set to `['data', 'error']` for example, the component will only re-render when the `data` or `error` properties change. - If set to `"tracked"`, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. -- `notifyOnChangePropsExclusions: string[]` - - Optional - - If set, the component will not re-render if any of the listed properties change. - - If set to `['isStale']` for example, the component will not re-render when the `isStale` property changes. - `onSuccess: (data: TData) => void` - Optional - This function will fire any time the query successfully fetches new data or the cache is updated via `setQueryData`. From 49069f747f76064c9f0530a1fe1677f33b4cefee Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 14:28:30 -0500 Subject: [PATCH 03/11] feat(QueryObserver): "tracked" as default behavior - remove "tracked" completely if notifyOnChangeProps is not defined, behave as v3 "tracked" - add `notifyOnChangeProps: 'all' to opt out of the smart tracking TODO: Now that default behavior has changed, work out the failed tests. Which parts to change for current ones and possibly write new ones. --- src/core/queryObserver.ts | 11 +++++------ src/core/types.ts | 2 +- src/react/tests/useQuery.test.tsx | 8 ++------ src/react/useBaseQuery.ts | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index d076963059..1a2095e05f 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -598,18 +598,17 @@ export class QueryObserver< const { notifyOnChangeProps } = this.options - if (!notifyOnChangeProps) { + if (notifyOnChangeProps === 'all') { return true } - if (notifyOnChangeProps === 'tracked' && !this.trackedProps.length) { + if (!notifyOnChangeProps && !this.trackedProps.length) { return true } - const includedProps = - notifyOnChangeProps === 'tracked' - ? this.trackedProps - : notifyOnChangeProps + const includedProps = !notifyOnChangeProps + ? this.trackedProps + : notifyOnChangeProps return Object.keys(result).some(key => { const typedKey = key as keyof QueryObserverResult diff --git a/src/core/types.ts b/src/core/types.ts index 8906ed7ddb..78ca519599 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -160,7 +160,7 @@ export interface QueryObserverOptions< * When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. * When set to `tracked`, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. */ - notifyOnChangeProps?: Array | 'tracked' + notifyOnChangeProps?: Array | 'all' /** * This callback will fire any time the query successfully fetches new data or the cache is updated via `setQueryData`. */ diff --git a/src/react/tests/useQuery.test.tsx b/src/react/tests/useQuery.test.tsx index ca117ecf94..43b715620f 100644 --- a/src/react/tests/useQuery.test.tsx +++ b/src/react/tests/useQuery.test.tsx @@ -922,9 +922,7 @@ describe('useQuery', () => { const states: UseQueryResult[] = [] function Page() { - const state = useQuery(key, () => 'test', { - notifyOnChangeProps: 'tracked', - }) + const state = useQuery(key, () => 'test') states.push(state) @@ -958,9 +956,7 @@ describe('useQuery', () => { const states: UseQueryResult[] = [] function Page() { - const state = useQuery(key, () => 'test', { - notifyOnChangeProps: 'tracked', - }) + const state = useQuery(key, () => 'test') states.push(state) diff --git a/src/react/useBaseQuery.ts b/src/react/useBaseQuery.ts index 693944fc38..a0a647f35b 100644 --- a/src/react/useBaseQuery.ts +++ b/src/react/useBaseQuery.ts @@ -143,7 +143,7 @@ export function useBaseQuery< } // Handle result property usage tracking - if (defaultedOptions.notifyOnChangeProps === 'tracked') { + if (!defaultedOptions.notifyOnChangeProps) { result = observer.trackResult(result) } From 74d72ed04bf7ab6a38b274af773cb85741a47a67 Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 16:29:11 -0500 Subject: [PATCH 04/11] test(useQuery): adjust tests to pass for notifyOnChangeProps udpate --- src/reactjs/tests/useQuery.test.tsx | 41 ++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/reactjs/tests/useQuery.test.tsx b/src/reactjs/tests/useQuery.test.tsx index 43b715620f..5f801158be 100644 --- a/src/reactjs/tests/useQuery.test.tsx +++ b/src/reactjs/tests/useQuery.test.tsx @@ -233,6 +233,7 @@ describe('useQuery', () => { return (

Status: {state.status}

+
Failure Count: {state.failureCount}
) } @@ -370,7 +371,10 @@ describe('useQuery', () => { const onSuccess = jest.fn() function Page() { - const state = useQuery(key, () => 'data', { onSuccess }) + const state = useQuery(key, () => 'data', { + onSuccess, + notifyOnChangeProps: 'all', + }) states.push(state) @@ -735,6 +739,7 @@ describe('useQuery', () => { }, { cacheTime: 0, + notifyOnChangeProps: 'all', } ) @@ -987,7 +992,7 @@ describe('useQuery', () => { function Page() { const [, rerender] = React.useState({}) - const state = useQuery(key, () => ++count) + const state = useQuery(key, () => ++count, { notifyOnChangeProps: 'all' }) states.push(state) @@ -1028,7 +1033,7 @@ describe('useQuery', () => { let count = 0 function Page() { - const state = useQuery(key, () => ++count) + const state = useQuery(key, () => ++count, { notifyOnChangeProps: 'all' }) states.push(state) @@ -1079,10 +1084,14 @@ describe('useQuery', () => { let count = 0 function Page() { - const state = useQuery(key, () => { - count++ - return count === 1 ? result1 : result2 - }) + const state = useQuery( + key, + () => { + count++ + return count === 1 ? result1 : result2 + }, + { notifyOnChangeProps: 'all' } + ) states.push(state) @@ -1455,6 +1464,7 @@ describe('useQuery', () => {

data: {state.data}

error: {state.error?.message}

+

previous data: {state.isPreviousData}

) } @@ -1616,7 +1626,7 @@ describe('useQuery', () => { await sleep(10) return count }, - { enabled: false, keepPreviousData: true } + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' } ) states.push(state) @@ -1705,7 +1715,7 @@ describe('useQuery', () => { await sleep(10) return count }, - { enabled: false, keepPreviousData: true } + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' } ) states.push(state) @@ -1775,7 +1785,7 @@ describe('useQuery', () => { const states: UseQueryResult[] = [] function FirstComponent() { - const state = useQuery(key, () => 1) + const state = useQuery(key, () => 1, { notifyOnChangeProps: 'all' }) const refetch = state.refetch states.push(state) @@ -1790,7 +1800,7 @@ describe('useQuery', () => { } function SecondComponent() { - useQuery(key, () => 2) + useQuery(key, () => 2, { notifyOnChangeProps: 'all' }) return null } @@ -3559,7 +3569,12 @@ describe('useQuery', () => { states.push(queryInfo) - return
count: {queryInfo.data}
+ return ( +
+

count: {queryInfo.data}

+

refetch: {queryInfo.isRefetching}

+
+ ) } const rendered = renderWithClient(queryClient, ) @@ -4117,7 +4132,7 @@ describe('useQuery', () => { count++ return count }, - { staleTime: Infinity, enabled: false } + { staleTime: Infinity, enabled: false, notifyOnChangeProps: 'all' } ) states.push(state) From 497d4acc3ad8c6af1b82d9b039f43982c357f47a Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 17:09:23 -0500 Subject: [PATCH 05/11] test(useInfiniteQuery): adjust tests to pass for notifyOnChangeProps udpate --- src/reactjs/tests/useInfiniteQuery.test.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/reactjs/tests/useInfiniteQuery.test.tsx b/src/reactjs/tests/useInfiniteQuery.test.tsx index 540b44956d..0eaa00c85b 100644 --- a/src/reactjs/tests/useInfiniteQuery.test.tsx +++ b/src/reactjs/tests/useInfiniteQuery.test.tsx @@ -186,6 +186,7 @@ describe('useInfiniteQuery', () => { { getNextPageParam: () => 1, keepPreviousData: true, + notifyOnChangeProps: 'all', } ) @@ -306,6 +307,7 @@ describe('useInfiniteQuery', () => { pages: [...data.pages].reverse(), pageParams: [...data.pageParams].reverse(), }), + notifyOnChangeProps: 'all', } ) @@ -359,6 +361,7 @@ describe('useInfiniteQuery', () => { }, { getPreviousPageParam: firstPage => firstPage - 1, + notifyOnChangeProps: 'all', } ) @@ -423,8 +426,10 @@ describe('useInfiniteQuery', () => { const states: UseInfiniteQueryResult[] = [] function Page() { - const state = useInfiniteQuery(key, ({ pageParam = 10 }) => - Number(pageParam) + const state = useInfiniteQuery( + key, + ({ pageParam = 10 }) => Number(pageParam), + { notifyOnChangeProps: 'all' } ) states.push(state) @@ -516,6 +521,7 @@ describe('useInfiniteQuery', () => { { getPreviousPageParam: firstPage => firstPage - 1, getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -608,6 +614,7 @@ describe('useInfiniteQuery', () => { ({ pageParam = 10 }) => Number(pageParam) * multiplier.current, { getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -687,6 +694,7 @@ describe('useInfiniteQuery', () => { }, { getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -913,6 +921,7 @@ describe('useInfiniteQuery', () => { }, { getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -1014,6 +1023,7 @@ describe('useInfiniteQuery', () => { }, { getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -1080,6 +1090,7 @@ describe('useInfiniteQuery', () => { }, { getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) @@ -1169,6 +1180,7 @@ describe('useInfiniteQuery', () => { { initialData: { pages: [1], pageParams: [1] }, getNextPageParam: lastPage => lastPage + 1, + notifyOnChangeProps: 'all', } ) From a34b4720675dad5ee6ebde401639f328c0c83122 Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 17:09:38 -0500 Subject: [PATCH 06/11] test(QueryResetErrorBoundary): adjust tests to pass for notifyOnChangeProps udpate --- src/reactjs/tests/QueryResetErrorBoundary.test.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx index f73210d251..5d31189c14 100644 --- a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx +++ b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx @@ -34,6 +34,7 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, + notifyOnChangeProps: 'all', } ) return
{data}
@@ -160,6 +161,7 @@ describe('QueryErrorResetBoundary', () => { retry: false, enabled, useErrorBoundary: true, + notifyOnChangeProps: 'all', } ) @@ -283,6 +285,7 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, + notifyOnChangeProps: 'all', } ) return
{data}
@@ -342,6 +345,7 @@ describe('QueryErrorResetBoundary', () => { retry: false, useErrorBoundary: true, initialData: 'initial', + notifyOnChangeProps: 'all', } ) return
{data}
@@ -402,6 +406,7 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, + notifyOnChangeProps: 'all', } ) return
{data}
@@ -465,6 +470,7 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, + notifyOnChangeProps: 'all', } ) return
{data}
From 17b21970feba33b2c3b7824b932b7e9043e88a6e Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Fri, 19 Nov 2021 17:11:18 -0500 Subject: [PATCH 07/11] refactor(QueryObserver): use nullish coalescing operator much cleaner than the negated if I started with --- src/core/queryObserver.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index 60621823cd..428f30e809 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -606,9 +606,7 @@ export class QueryObserver< return true } - const includedProps = !notifyOnChangeProps - ? this.trackedProps - : notifyOnChangeProps + const includedProps = notifyOnChangeProps ?? this.trackedProps return Object.keys(result).some(key => { const typedKey = key as keyof QueryObserverResult From c57e400a75a2b7fb1ba2e6f2cfe30dc718374c7e Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Sat, 20 Nov 2021 10:49:01 -0500 Subject: [PATCH 08/11] test(QueryResetErrorBoundary): remove "tracked" from test --- src/reactjs/tests/QueryResetErrorBoundary.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx index 3f0b452765..6aa1f947a3 100644 --- a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx +++ b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx @@ -619,7 +619,6 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, - notifyOnChangeProps: 'tracked', } ) return
{data}
From fcd615c417956b944323d40a22d0789e95188ef4 Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Sat, 20 Nov 2021 10:54:31 -0500 Subject: [PATCH 09/11] revert: test(QueryResetErrorBoundary): adjust tests to pass for notifyOnChaneProps udpate This reverts commit a34b4720675dad5ee6ebde401639f328c0c83122. The changes are not necessary after PR #2993 fix. --- src/reactjs/tests/QueryResetErrorBoundary.test.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx index 6aa1f947a3..5e304c6f99 100644 --- a/src/reactjs/tests/QueryResetErrorBoundary.test.tsx +++ b/src/reactjs/tests/QueryResetErrorBoundary.test.tsx @@ -34,7 +34,6 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, - notifyOnChangeProps: 'all', } ) return
{data}
@@ -161,7 +160,6 @@ describe('QueryErrorResetBoundary', () => { retry: false, enabled, useErrorBoundary: true, - notifyOnChangeProps: 'all', } ) @@ -285,7 +283,6 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, - notifyOnChangeProps: 'all', } ) return
{data}
@@ -345,7 +342,6 @@ describe('QueryErrorResetBoundary', () => { retry: false, useErrorBoundary: true, initialData: 'initial', - notifyOnChangeProps: 'all', } ) return
{data}
@@ -406,7 +402,6 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, - notifyOnChangeProps: 'all', } ) return
{data}
@@ -470,7 +465,6 @@ describe('QueryErrorResetBoundary', () => { { retry: false, useErrorBoundary: true, - notifyOnChangeProps: 'all', } ) return
{data}
From 0f4bf90bfd5114c37a32f29d60daf6144c8aca8c Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Sat, 20 Nov 2021 10:59:03 -0500 Subject: [PATCH 10/11] refactor(QueryObserver): combine prop checks --- src/core/queryObserver.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index 8ff80719fd..0cc8d3b8c1 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -612,11 +612,10 @@ export class QueryObserver< const { notifyOnChangeProps } = this.options - if (notifyOnChangeProps === 'all') { - return true - } - - if (!notifyOnChangeProps && !this.trackedProps.length) { + if ( + notifyOnChangeProps === 'all' || + (!notifyOnChangeProps && !this.trackedProps.length) + ) { return true } From 10215b03b798d9f9a271784b1aba1f09034689eb Mon Sep 17 00:00:00 2001 From: Rene Dellefont Date: Sat, 20 Nov 2021 11:22:26 -0500 Subject: [PATCH 11/11] docs(notifyOnChangeProps): update docs to reflect new api --- docs/src/pages/comparison.md | 2 +- docs/src/pages/guides/migrating-to-react-query-4.md | 6 ++++++ docs/src/pages/reference/useQuery.md | 5 +++-- src/core/types.ts | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/src/pages/comparison.md b/docs/src/pages/comparison.md index 4a3691ed4c..dfa06c741d 100644 --- a/docs/src/pages/comparison.md +++ b/docs/src/pages/comparison.md @@ -64,7 +64,7 @@ Feature/Capability Key: > **1 Lagged Query Data** - React 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. -> **2 Render Optimization** - React 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. React 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']`. Set `notifyOnChangeProps: 'tracked'` to automatically track which fields are accessed and only re-render if one of them changes. +> **2 Render Optimization** - React Query has excellent rendering performance. By default, it will automatically track which fields are accessed and only re-render if one of them changes. If you would like to opt-out of this optimization, setting `notifyOnChangeProps` to `'all'` will re-render your components whenever the query is updated. For example because it has new data, or to indicate it is fetching. React 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']`. > **3 Partial query matching** - Because React 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. diff --git a/docs/src/pages/guides/migrating-to-react-query-4.md b/docs/src/pages/guides/migrating-to-react-query-4.md index b8d560867d..539813f1d4 100644 --- a/docs/src/pages/guides/migrating-to-react-query-4.md +++ b/docs/src/pages/guides/migrating-to-react-query-4.md @@ -27,6 +27,12 @@ With version [3.22.0](https://github.com/tannerlinsley/react-query/releases/tag/ + import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query' ``` +### `notifyOnChangeProps` property no longer accepts `"tracked"` as a value + +The `notifyOnChangeProps` option no longer accepts a `"tracked"` value. Instead, `useQuery` defaults to tracking properties. All queries using `notifyOnChangeProps: "tracked"` should be updated by removing this option. + +If you would like to bypass this in any queries to emulate the v3 default behavior of re-rendering whenever a query changes, `notifyOnChangeProps` now accepts an `"all"` value to opt-out of the default smart tracking optimization. + ### `notifyOnChangePropsExclusion` has been removed In v4, `notifyOnChangeProps` defaults to the `"tracked"` behavior of v3 instead of `undefined`. Now that `"tracked"` is the default behavior for v4, it no longer makes sense to include this config option. diff --git a/docs/src/pages/reference/useQuery.md b/docs/src/pages/reference/useQuery.md index 4bca601c3f..5afeee10ae 100644 --- a/docs/src/pages/reference/useQuery.md +++ b/docs/src/pages/reference/useQuery.md @@ -124,11 +124,12 @@ const result = useQuery({ - If set to `true`, the query will refetch on reconnect if the data is stale. - If set to `false`, the query will not refetch on reconnect. - If set to `"always"`, the query will always refetch on reconnect. -- `notifyOnChangeProps: string[] | "tracked"` +- `notifyOnChangeProps: string[] | "all"` - Optional - If set, the component will only re-render if any of the listed properties change. - If set to `['data', 'error']` for example, the component will only re-render when the `data` or `error` properties change. - - If set to `"tracked"`, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. + - If set to `"all"`, the component will opt-out of smart tracking and re-render whenever a query is updated. + - By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. - `onSuccess: (data: TData) => void` - Optional - This function will fire any time the query successfully fetches new data. diff --git a/src/core/types.ts b/src/core/types.ts index 00f92bc38a..e9bf309ae4 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -154,7 +154,8 @@ export interface QueryObserverOptions< /** * If set, the component will only re-render if any of the listed properties change. * When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. - * When set to `tracked`, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. + * When set to `'all'`, the component will re-render whenever a query is updated. + * By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change. */ notifyOnChangeProps?: Array | 'all' /**