@tanstack/react-query 4.29.23 → 4.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/Hydrate.d.ts.map +1 -1
- package/build/lib/Hydrate.esm.js.map +1 -1
- package/build/lib/Hydrate.js.map +1 -1
- package/build/lib/Hydrate.mjs.map +1 -1
- package/build/lib/__tests__/utils.d.ts +1 -1
- package/build/lib/__tests__/utils.d.ts.map +1 -1
- package/build/lib/errorBoundaryUtils.d.ts.map +1 -1
- package/build/lib/errorBoundaryUtils.esm.js.map +1 -1
- package/build/lib/errorBoundaryUtils.js.map +1 -1
- package/build/lib/errorBoundaryUtils.mjs.map +1 -1
- package/build/lib/reactBatchedUpdates.d.ts.map +1 -1
- package/build/lib/reactBatchedUpdates.esm.js.map +1 -1
- package/build/lib/reactBatchedUpdates.js.map +1 -1
- package/build/lib/reactBatchedUpdates.mjs.map +1 -1
- package/build/lib/reactBatchedUpdates.native.d.ts.map +1 -1
- package/build/lib/types.d.ts +1 -1
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/useBaseQuery.d.ts.map +1 -1
- package/build/lib/useBaseQuery.esm.js +1 -1
- package/build/lib/useBaseQuery.esm.js.map +1 -1
- package/build/lib/useBaseQuery.js +1 -1
- package/build/lib/useBaseQuery.js.map +1 -1
- package/build/lib/useBaseQuery.mjs +1 -1
- package/build/lib/useBaseQuery.mjs.map +1 -1
- package/build/lib/useInfiniteQuery.d.ts.map +1 -1
- package/build/lib/useInfiniteQuery.esm.js.map +1 -1
- package/build/lib/useInfiniteQuery.js.map +1 -1
- package/build/lib/useInfiniteQuery.mjs.map +1 -1
- package/build/lib/useIsFetching.d.ts +1 -1
- package/build/lib/useIsFetching.d.ts.map +1 -1
- package/build/lib/useIsFetching.esm.js.map +1 -1
- package/build/lib/useIsFetching.js.map +1 -1
- package/build/lib/useIsFetching.mjs.map +1 -1
- package/build/lib/useIsMutating.d.ts +1 -1
- package/build/lib/useIsMutating.d.ts.map +1 -1
- package/build/lib/useIsMutating.esm.js +1 -1
- package/build/lib/useIsMutating.esm.js.map +1 -1
- package/build/lib/useIsMutating.js +1 -1
- package/build/lib/useIsMutating.js.map +1 -1
- package/build/lib/useIsMutating.mjs +1 -1
- package/build/lib/useIsMutating.mjs.map +1 -1
- package/build/lib/useMutation.d.ts.map +1 -1
- package/build/lib/useMutation.esm.js +1 -1
- package/build/lib/useMutation.esm.js.map +1 -1
- package/build/lib/useMutation.js +1 -1
- package/build/lib/useMutation.js.map +1 -1
- package/build/lib/useMutation.mjs +1 -1
- package/build/lib/useMutation.mjs.map +1 -1
- package/build/lib/useQueries.d.ts +1 -1
- package/build/lib/useQueries.d.ts.map +1 -1
- package/build/lib/useQueries.esm.js +1 -3
- package/build/lib/useQueries.esm.js.map +1 -1
- package/build/lib/useQueries.js +1 -3
- package/build/lib/useQueries.js.map +1 -1
- package/build/lib/useQueries.mjs +1 -3
- package/build/lib/useQueries.mjs.map +1 -1
- package/build/lib/useQuery.d.ts.map +1 -1
- package/build/lib/useQuery.esm.js.map +1 -1
- package/build/lib/useQuery.js.map +1 -1
- package/build/lib/useQuery.mjs.map +1 -1
- package/build/umd/index.development.js +3 -4
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Hydrate.tsx +1 -1
- package/src/__tests__/Hydrate.test.tsx +4 -4
- package/src/__tests__/QueryClientProvider.test.tsx +2 -2
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +1 -1
- package/src/__tests__/ssr-hydration.test.tsx +2 -2
- package/src/__tests__/ssr.test.tsx +2 -2
- package/src/__tests__/suspense.test.tsx +1 -1
- package/src/__tests__/useInfiniteQuery.test.tsx +1 -1
- package/src/__tests__/useIsFetching.test.tsx +1 -1
- package/src/__tests__/useIsMutating.test.tsx +3 -3
- package/src/__tests__/useMutation.test.tsx +2 -2
- package/src/__tests__/useQueries.test.tsx +1 -1
- package/src/__tests__/useQuery.test.tsx +252 -85
- package/src/__tests__/utils.tsx +2 -2
- package/src/errorBoundaryUtils.ts +2 -2
- package/src/reactBatchedUpdates.native.ts +1 -0
- package/src/reactBatchedUpdates.ts +1 -0
- package/src/types.ts +4 -4
- package/src/useBaseQuery.ts +4 -4
- package/src/useInfiniteQuery.ts +3 -3
- package/src/useIsFetching.ts +2 -2
- package/src/useIsMutating.ts +3 -3
- package/src/useMutation.ts +5 -5
- package/src/useQueries.ts +5 -5
- package/src/useQuery.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-query",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.30.0",
|
|
4
4
|
"description": "Hooks for managing, caching and syncing asynchronous and remote data in React",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"use-sync-external-store": "^1.2.0",
|
|
50
|
-
"@tanstack/query-core": "4.
|
|
50
|
+
"@tanstack/query-core": "4.30.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
package/src/Hydrate.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
|
|
4
|
-
import type { HydrateOptions } from '@tanstack/query-core'
|
|
5
4
|
import { hydrate } from '@tanstack/query-core'
|
|
6
5
|
import { useQueryClient } from './QueryClientProvider'
|
|
6
|
+
import type { HydrateOptions } from '@tanstack/query-core'
|
|
7
7
|
import type { ContextOptions } from './types'
|
|
8
8
|
|
|
9
9
|
export function useHydrate(
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { render } from '@testing-library/react'
|
|
3
3
|
|
|
4
|
+
import * as coreModule from '@tanstack/query-core'
|
|
4
5
|
import {
|
|
6
|
+
Hydrate,
|
|
7
|
+
QueryCache,
|
|
5
8
|
QueryClient,
|
|
6
9
|
QueryClientProvider,
|
|
7
|
-
QueryCache,
|
|
8
|
-
useQuery,
|
|
9
10
|
dehydrate,
|
|
10
11
|
useHydrate,
|
|
11
|
-
|
|
12
|
+
useQuery,
|
|
12
13
|
} from '@tanstack/react-query'
|
|
13
14
|
import { createQueryClient, sleep } from './utils'
|
|
14
|
-
import * as coreModule from '@tanstack/query-core'
|
|
15
15
|
|
|
16
16
|
describe('React hydration', () => {
|
|
17
17
|
const fetchData: (value: string) => Promise<string> = (value) =>
|
|
@@ -2,14 +2,14 @@ import * as React from 'react'
|
|
|
2
2
|
import { render, waitFor } from '@testing-library/react'
|
|
3
3
|
import { renderToString } from 'react-dom/server'
|
|
4
4
|
|
|
5
|
-
import { sleep, queryKey, createQueryClient } from './utils'
|
|
6
5
|
import {
|
|
6
|
+
QueryCache,
|
|
7
7
|
QueryClient,
|
|
8
8
|
QueryClientProvider,
|
|
9
|
-
QueryCache,
|
|
10
9
|
useQuery,
|
|
11
10
|
useQueryClient,
|
|
12
11
|
} from '..'
|
|
12
|
+
import { createQueryClient, queryKey, sleep } from './utils'
|
|
13
13
|
|
|
14
14
|
describe('QueryClientProvider', () => {
|
|
15
15
|
test('sets a specific cache for all queries to use', async () => {
|
|
@@ -2,8 +2,8 @@ import { fireEvent, waitFor } from '@testing-library/react'
|
|
|
2
2
|
import { ErrorBoundary } from 'react-error-boundary'
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
|
|
5
|
-
import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
|
|
6
5
|
import { QueryCache, QueryErrorResetBoundary, useQueries, useQuery } from '..'
|
|
6
|
+
import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
|
|
7
7
|
|
|
8
8
|
// TODO: This should be removed with the types for react-error-boundary get updated.
|
|
9
9
|
declare module 'react-error-boundary' {
|
|
@@ -6,11 +6,11 @@ import ReactDOMServer from 'react-dom/server'
|
|
|
6
6
|
import type {} from 'react-dom/next'
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
useQuery,
|
|
10
|
-
QueryClientProvider,
|
|
11
9
|
QueryCache,
|
|
10
|
+
QueryClientProvider,
|
|
12
11
|
dehydrate,
|
|
13
12
|
hydrate,
|
|
13
|
+
useQuery,
|
|
14
14
|
} from '..'
|
|
15
15
|
import { createQueryClient, setIsServer, sleep } from './utils'
|
|
16
16
|
|
|
@@ -6,8 +6,8 @@ import * as React from 'react'
|
|
|
6
6
|
// @ts-ignore
|
|
7
7
|
import { renderToString } from 'react-dom/server'
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { QueryCache, QueryClientProvider, useInfiniteQuery, useQuery } from '..'
|
|
10
|
+
import { createQueryClient, queryKey, sleep } from './utils'
|
|
11
11
|
|
|
12
12
|
describe('Server Side Rendering', () => {
|
|
13
13
|
it('should not trigger fetch', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { fireEvent, waitFor } from '@testing-library/react'
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
import { ErrorBoundary } from 'react-error-boundary'
|
|
4
|
-
import type { UseInfiniteQueryResult, UseQueryResult } from '..'
|
|
5
4
|
import {
|
|
6
5
|
QueryCache,
|
|
7
6
|
QueryErrorResetBoundary,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
useQueryErrorResetBoundary,
|
|
12
11
|
} from '..'
|
|
13
12
|
import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
|
|
13
|
+
import type { UseInfiniteQueryResult, UseQueryResult } from '..'
|
|
14
14
|
|
|
15
15
|
describe("useQuery's in Suspense mode", () => {
|
|
16
16
|
const queryCache = new QueryCache()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { fireEvent, waitFor } from '@testing-library/react'
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
|
|
4
|
+
import { QueryCache, useInfiniteQuery } from '..'
|
|
4
5
|
import {
|
|
5
6
|
createQueryClient,
|
|
6
7
|
queryKey,
|
|
@@ -13,7 +14,6 @@ import type {
|
|
|
13
14
|
QueryFunctionContext,
|
|
14
15
|
UseInfiniteQueryResult,
|
|
15
16
|
} from '..'
|
|
16
|
-
import { QueryCache, useInfiniteQuery } from '..'
|
|
17
17
|
|
|
18
18
|
interface Result {
|
|
19
19
|
items: number[]
|
|
@@ -2,6 +2,7 @@ import { fireEvent, waitFor } from '@testing-library/react'
|
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
import { ErrorBoundary } from 'react-error-boundary'
|
|
4
4
|
|
|
5
|
+
import { QueryCache, useIsFetching, useQuery } from '..'
|
|
5
6
|
import {
|
|
6
7
|
createQueryClient,
|
|
7
8
|
queryKey,
|
|
@@ -10,7 +11,6 @@ import {
|
|
|
10
11
|
sleep,
|
|
11
12
|
} from './utils'
|
|
12
13
|
import type { QueryClient } from '..'
|
|
13
|
-
import { QueryCache, useIsFetching, useQuery } from '..'
|
|
14
14
|
|
|
15
15
|
describe('useIsFetching', () => {
|
|
16
16
|
// See https://github.com/tannerlinsley/react-query/issues/105
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { fireEvent, waitFor } from '@testing-library/react'
|
|
2
2
|
import * as React from 'react'
|
|
3
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
4
|
+
import { QueryClient } from '@tanstack/query-core'
|
|
3
5
|
import { useIsMutating } from '../useIsMutating'
|
|
4
6
|
import { useMutation } from '../useMutation'
|
|
7
|
+
import * as MutationCacheModule from '../../../query-core/src/mutationCache'
|
|
5
8
|
import {
|
|
6
9
|
createQueryClient,
|
|
7
10
|
renderWithClient,
|
|
8
11
|
setActTimeout,
|
|
9
12
|
sleep,
|
|
10
13
|
} from './utils'
|
|
11
|
-
import { ErrorBoundary } from 'react-error-boundary'
|
|
12
|
-
import { QueryClient } from '@tanstack/query-core'
|
|
13
|
-
import * as MutationCacheModule from '../../../query-core/src/mutationCache'
|
|
14
14
|
|
|
15
15
|
describe('useIsMutating', () => {
|
|
16
16
|
it('should return the number of fetching mutations', async () => {
|
|
@@ -3,9 +3,7 @@ import '@testing-library/jest-dom'
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { ErrorBoundary } from 'react-error-boundary'
|
|
5
5
|
|
|
6
|
-
import type { QueryClient } from '..'
|
|
7
6
|
import { MutationCache, QueryCache, useMutation } from '..'
|
|
8
|
-
import type { UseMutationResult } from '../types'
|
|
9
7
|
import {
|
|
10
8
|
createQueryClient,
|
|
11
9
|
mockNavigatorOnLine,
|
|
@@ -14,6 +12,8 @@ import {
|
|
|
14
12
|
setActTimeout,
|
|
15
13
|
sleep,
|
|
16
14
|
} from './utils'
|
|
15
|
+
import type { QueryClient } from '..'
|
|
16
|
+
import type { UseMutationResult } from '../types'
|
|
17
17
|
|
|
18
18
|
describe('useMutation', () => {
|
|
19
19
|
const queryCache = new QueryCache()
|
|
@@ -4,6 +4,7 @@ import { ErrorBoundary } from 'react-error-boundary'
|
|
|
4
4
|
|
|
5
5
|
import * as QueriesObserverModule from '../../../query-core/src/queriesObserver'
|
|
6
6
|
|
|
7
|
+
import { QueriesObserver, QueryCache, useQueries } from '..'
|
|
7
8
|
import {
|
|
8
9
|
createQueryClient,
|
|
9
10
|
expectType,
|
|
@@ -20,7 +21,6 @@ import type {
|
|
|
20
21
|
UseQueryOptions,
|
|
21
22
|
UseQueryResult,
|
|
22
23
|
} from '..'
|
|
23
|
-
import { QueriesObserver, QueryCache, useQueries } from '..'
|
|
24
24
|
import type { QueryFunctionContext } from '@tanstack/query-core'
|
|
25
25
|
|
|
26
26
|
describe('useQueries', () => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { act, fireEvent, waitFor } from '@testing-library/react'
|
|
2
2
|
import '@testing-library/jest-dom'
|
|
3
3
|
import * as React from 'react'
|
|
4
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
5
|
+
import { QueryCache, useQuery } from '..'
|
|
4
6
|
import {
|
|
5
7
|
Blink,
|
|
6
8
|
createQueryClient,
|
|
@@ -20,8 +22,6 @@ import type {
|
|
|
20
22
|
UseQueryOptions,
|
|
21
23
|
UseQueryResult,
|
|
22
24
|
} from '..'
|
|
23
|
-
import { QueryCache, useQuery } from '..'
|
|
24
|
-
import { ErrorBoundary } from 'react-error-boundary'
|
|
25
25
|
|
|
26
26
|
describe('useQuery', () => {
|
|
27
27
|
const queryCache = new QueryCache()
|
|
@@ -1018,46 +1018,6 @@ describe('useQuery', () => {
|
|
|
1018
1018
|
expect(states[1]).toMatchObject({ data: 'test' })
|
|
1019
1019
|
})
|
|
1020
1020
|
|
|
1021
|
-
it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
|
|
1022
|
-
const key = queryKey()
|
|
1023
|
-
const states: UseQueryResult<string>[] = []
|
|
1024
|
-
|
|
1025
|
-
function Page() {
|
|
1026
|
-
const state = useQuery(key, () => ({ name: 'test' }), {
|
|
1027
|
-
select: (data) => data.name,
|
|
1028
|
-
notifyOnChangeProps: ['data'],
|
|
1029
|
-
})
|
|
1030
|
-
|
|
1031
|
-
states.push(state)
|
|
1032
|
-
|
|
1033
|
-
return (
|
|
1034
|
-
<div>
|
|
1035
|
-
<div>{state.data}</div>
|
|
1036
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
1037
|
-
</div>
|
|
1038
|
-
)
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
1042
|
-
|
|
1043
|
-
await waitFor(() => {
|
|
1044
|
-
rendered.getByText('test')
|
|
1045
|
-
})
|
|
1046
|
-
|
|
1047
|
-
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
1048
|
-
|
|
1049
|
-
await waitFor(() => {
|
|
1050
|
-
rendered.getByText('test')
|
|
1051
|
-
})
|
|
1052
|
-
|
|
1053
|
-
expect(states[0]).toMatchObject({ data: undefined })
|
|
1054
|
-
expect(states[1]).toMatchObject({ data: 'test' })
|
|
1055
|
-
|
|
1056
|
-
// make sure no additional renders happen
|
|
1057
|
-
await sleep(50)
|
|
1058
|
-
expect(states.length).toBe(2)
|
|
1059
|
-
})
|
|
1060
|
-
|
|
1061
1021
|
it('should throw an error when a selector throws', async () => {
|
|
1062
1022
|
const key = queryKey()
|
|
1063
1023
|
const states: UseQueryResult<string>[] = []
|
|
@@ -2223,60 +2183,267 @@ describe('useQuery', () => {
|
|
|
2223
2183
|
expect(states[2]).toMatchObject({ isStale: true })
|
|
2224
2184
|
})
|
|
2225
2185
|
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2186
|
+
describe('notifyOnChangeProps', () => {
|
|
2187
|
+
it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
|
|
2188
|
+
const key = queryKey()
|
|
2189
|
+
const states: UseQueryResult<string>[] = []
|
|
2229
2190
|
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2191
|
+
function Page() {
|
|
2192
|
+
const state = useQuery(
|
|
2193
|
+
key,
|
|
2194
|
+
async () => {
|
|
2195
|
+
await sleep(5)
|
|
2196
|
+
return 'test'
|
|
2197
|
+
},
|
|
2198
|
+
{
|
|
2199
|
+
notifyOnChangeProps: ['data'],
|
|
2200
|
+
},
|
|
2201
|
+
)
|
|
2241
2202
|
|
|
2242
|
-
|
|
2203
|
+
states.push(state)
|
|
2243
2204
|
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2205
|
+
return (
|
|
2206
|
+
<>
|
|
2207
|
+
<button
|
|
2208
|
+
onClick={async () => {
|
|
2209
|
+
await state.refetch()
|
|
2210
|
+
}}
|
|
2211
|
+
>
|
|
2212
|
+
refetch
|
|
2213
|
+
</button>
|
|
2253
2214
|
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2215
|
+
<div>{state.data}</div>
|
|
2216
|
+
</>
|
|
2217
|
+
)
|
|
2218
|
+
}
|
|
2258
2219
|
|
|
2259
|
-
|
|
2220
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2260
2221
|
|
|
2261
|
-
|
|
2262
|
-
|
|
2222
|
+
await waitFor(() => {
|
|
2223
|
+
rendered.getByText('test')
|
|
2224
|
+
})
|
|
2225
|
+
|
|
2226
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2227
|
+
|
|
2228
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2229
|
+
await sleep(20)
|
|
2230
|
+
|
|
2231
|
+
expect(states.length).toBe(2)
|
|
2232
|
+
expect(states[0]).toMatchObject({
|
|
2233
|
+
data: undefined,
|
|
2234
|
+
status: 'loading',
|
|
2235
|
+
isFetching: true,
|
|
2236
|
+
})
|
|
2237
|
+
expect(states[1]).toMatchObject({
|
|
2238
|
+
data: 'test',
|
|
2239
|
+
status: 'success',
|
|
2240
|
+
isFetching: false,
|
|
2241
|
+
})
|
|
2263
2242
|
})
|
|
2264
2243
|
|
|
2265
|
-
|
|
2244
|
+
it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
|
|
2245
|
+
const key = queryKey()
|
|
2246
|
+
const states: UseQueryResult<string>[] = []
|
|
2266
2247
|
|
|
2267
|
-
|
|
2268
|
-
|
|
2248
|
+
function Page() {
|
|
2249
|
+
const state = useQuery(key, () => ({ name: 'test' }), {
|
|
2250
|
+
select: (data) => data.name,
|
|
2251
|
+
notifyOnChangeProps: ['data'],
|
|
2252
|
+
})
|
|
2269
2253
|
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2254
|
+
states.push(state)
|
|
2255
|
+
|
|
2256
|
+
return (
|
|
2257
|
+
<div>
|
|
2258
|
+
<div>{state.data}</div>
|
|
2259
|
+
<button onClick={() => state.refetch()}>refetch</button>
|
|
2260
|
+
</div>
|
|
2261
|
+
)
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2265
|
+
|
|
2266
|
+
await waitFor(() => {
|
|
2267
|
+
rendered.getByText('test')
|
|
2268
|
+
})
|
|
2269
|
+
|
|
2270
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2271
|
+
|
|
2272
|
+
await waitFor(() => {
|
|
2273
|
+
rendered.getByText('test')
|
|
2274
|
+
})
|
|
2275
|
+
|
|
2276
|
+
expect(states[0]).toMatchObject({ data: undefined })
|
|
2277
|
+
expect(states[1]).toMatchObject({ data: 'test' })
|
|
2278
|
+
|
|
2279
|
+
// make sure no additional renders happen
|
|
2280
|
+
await sleep(50)
|
|
2281
|
+
expect(states.length).toBe(2)
|
|
2275
2282
|
})
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2283
|
+
|
|
2284
|
+
// See https://github.com/TanStack/query/discussions/5588
|
|
2285
|
+
describe('function', () => {
|
|
2286
|
+
it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
|
|
2287
|
+
const key = queryKey()
|
|
2288
|
+
const states: UseQueryResult<string>[] = []
|
|
2289
|
+
|
|
2290
|
+
function Page() {
|
|
2291
|
+
const state = useQuery(
|
|
2292
|
+
key,
|
|
2293
|
+
async () => {
|
|
2294
|
+
await sleep(5)
|
|
2295
|
+
return 'test'
|
|
2296
|
+
},
|
|
2297
|
+
{
|
|
2298
|
+
notifyOnChangeProps: () => ['data'],
|
|
2299
|
+
},
|
|
2300
|
+
)
|
|
2301
|
+
|
|
2302
|
+
states.push(state)
|
|
2303
|
+
|
|
2304
|
+
return (
|
|
2305
|
+
<>
|
|
2306
|
+
<button
|
|
2307
|
+
onClick={async () => {
|
|
2308
|
+
await state.refetch()
|
|
2309
|
+
}}
|
|
2310
|
+
>
|
|
2311
|
+
refetch
|
|
2312
|
+
</button>
|
|
2313
|
+
|
|
2314
|
+
<div>{state.data}</div>
|
|
2315
|
+
</>
|
|
2316
|
+
)
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2320
|
+
|
|
2321
|
+
await waitFor(() => {
|
|
2322
|
+
rendered.getByText('test')
|
|
2323
|
+
})
|
|
2324
|
+
|
|
2325
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2326
|
+
|
|
2327
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2328
|
+
await sleep(20)
|
|
2329
|
+
|
|
2330
|
+
expect(states.length).toBe(2)
|
|
2331
|
+
expect(states[0]).toMatchObject({
|
|
2332
|
+
data: undefined,
|
|
2333
|
+
status: 'loading',
|
|
2334
|
+
isFetching: true,
|
|
2335
|
+
})
|
|
2336
|
+
expect(states[1]).toMatchObject({
|
|
2337
|
+
data: 'test',
|
|
2338
|
+
status: 'success',
|
|
2339
|
+
isFetching: false,
|
|
2340
|
+
})
|
|
2341
|
+
})
|
|
2342
|
+
|
|
2343
|
+
it('should not re-render when change props are not actively being tracked', async () => {
|
|
2344
|
+
const key = queryKey()
|
|
2345
|
+
const states: UseQueryResult<string>[] = []
|
|
2346
|
+
|
|
2347
|
+
function Page() {
|
|
2348
|
+
const fetchCounterRef = React.useRef(0)
|
|
2349
|
+
const trackChangesRef = React.useRef(true)
|
|
2350
|
+
|
|
2351
|
+
const notifyOnChangeProps = React.useCallback(() => {
|
|
2352
|
+
return trackChangesRef.current ? 'all' : []
|
|
2353
|
+
}, [])
|
|
2354
|
+
|
|
2355
|
+
const state = useQuery(
|
|
2356
|
+
key,
|
|
2357
|
+
async () => {
|
|
2358
|
+
await sleep(5)
|
|
2359
|
+
fetchCounterRef.current++
|
|
2360
|
+
return `fetch counter: ${fetchCounterRef.current}`
|
|
2361
|
+
},
|
|
2362
|
+
{
|
|
2363
|
+
notifyOnChangeProps,
|
|
2364
|
+
},
|
|
2365
|
+
)
|
|
2366
|
+
|
|
2367
|
+
states.push(state)
|
|
2368
|
+
|
|
2369
|
+
return (
|
|
2370
|
+
<>
|
|
2371
|
+
<button
|
|
2372
|
+
onClick={async () => {
|
|
2373
|
+
await state.refetch()
|
|
2374
|
+
}}
|
|
2375
|
+
>
|
|
2376
|
+
refetch
|
|
2377
|
+
</button>
|
|
2378
|
+
<button
|
|
2379
|
+
onClick={() => {
|
|
2380
|
+
trackChangesRef.current = true
|
|
2381
|
+
}}
|
|
2382
|
+
>
|
|
2383
|
+
enableTracking
|
|
2384
|
+
</button>
|
|
2385
|
+
<button
|
|
2386
|
+
onClick={() => {
|
|
2387
|
+
trackChangesRef.current = false
|
|
2388
|
+
}}
|
|
2389
|
+
>
|
|
2390
|
+
disableTracking
|
|
2391
|
+
</button>
|
|
2392
|
+
|
|
2393
|
+
<div>{state.data}</div>
|
|
2394
|
+
</>
|
|
2395
|
+
)
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2399
|
+
await waitFor(() => {
|
|
2400
|
+
rendered.getByText('fetch counter: 1')
|
|
2401
|
+
})
|
|
2402
|
+
|
|
2403
|
+
expect(states.length).toBe(2)
|
|
2404
|
+
expect(states[0]).toMatchObject({
|
|
2405
|
+
data: undefined,
|
|
2406
|
+
isFetching: true,
|
|
2407
|
+
status: 'loading',
|
|
2408
|
+
})
|
|
2409
|
+
expect(states[1]).toMatchObject({
|
|
2410
|
+
data: 'fetch counter: 1',
|
|
2411
|
+
status: 'success',
|
|
2412
|
+
isFetching: false,
|
|
2413
|
+
})
|
|
2414
|
+
|
|
2415
|
+
// disable tracking and refetch to check for re-renders
|
|
2416
|
+
fireEvent.click(
|
|
2417
|
+
rendered.getByRole('button', { name: 'disableTracking' }),
|
|
2418
|
+
)
|
|
2419
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2420
|
+
|
|
2421
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2422
|
+
await sleep(20)
|
|
2423
|
+
// still expect to only have two re-renders from the initial fetch
|
|
2424
|
+
expect(states.length).toBe(2)
|
|
2425
|
+
|
|
2426
|
+
// enable tracking and refetch to check for re-renders
|
|
2427
|
+
fireEvent.click(
|
|
2428
|
+
rendered.getByRole('button', { name: 'enableTracking' }),
|
|
2429
|
+
)
|
|
2430
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2431
|
+
|
|
2432
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2433
|
+
await sleep(20)
|
|
2434
|
+
|
|
2435
|
+
expect(states.length).toBe(4)
|
|
2436
|
+
expect(states[2]).toMatchObject({
|
|
2437
|
+
data: 'fetch counter: 2',
|
|
2438
|
+
status: 'success',
|
|
2439
|
+
isFetching: true,
|
|
2440
|
+
})
|
|
2441
|
+
expect(states[3]).toMatchObject({
|
|
2442
|
+
data: 'fetch counter: 3',
|
|
2443
|
+
status: 'success',
|
|
2444
|
+
isFetching: false,
|
|
2445
|
+
})
|
|
2446
|
+
})
|
|
2280
2447
|
})
|
|
2281
2448
|
})
|
|
2282
2449
|
|
package/src/__tests__/utils.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { act, render } from '@testing-library/react'
|
|
3
|
-
import type { ContextOptions, QueryClientConfig, MutationOptions } from '..'
|
|
4
|
-
import { QueryClient, QueryClientProvider } from '..'
|
|
5
3
|
import * as utils from '@tanstack/query-core'
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '..'
|
|
5
|
+
import type { ContextOptions, MutationOptions, QueryClientConfig } from '..'
|
|
6
6
|
|
|
7
7
|
export function renderWithClient(
|
|
8
8
|
client: QueryClient,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { shouldThrowError } from './utils'
|
|
2
4
|
import type {
|
|
3
5
|
DefaultedQueryObserverOptions,
|
|
4
6
|
Query,
|
|
@@ -7,8 +9,6 @@ import type {
|
|
|
7
9
|
UseErrorBoundary,
|
|
8
10
|
} from '@tanstack/query-core'
|
|
9
11
|
import type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'
|
|
10
|
-
import * as React from 'react'
|
|
11
|
-
import { shouldThrowError } from './utils'
|
|
12
12
|
|
|
13
13
|
export const ensurePreventErrorBoundaryRetry = <
|
|
14
14
|
TQueryFnData,
|
package/src/types.ts
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import type * as React from 'react'
|
|
4
4
|
import type {
|
|
5
|
+
DefinedQueryObserverResult,
|
|
5
6
|
InfiniteQueryObserverOptions,
|
|
6
7
|
InfiniteQueryObserverResult,
|
|
8
|
+
MutateFunction,
|
|
9
|
+
MutationObserverOptions,
|
|
7
10
|
MutationObserverResult,
|
|
11
|
+
QueryKey,
|
|
8
12
|
QueryObserverOptions,
|
|
9
13
|
QueryObserverResult,
|
|
10
|
-
QueryKey,
|
|
11
|
-
MutationObserverOptions,
|
|
12
|
-
MutateFunction,
|
|
13
|
-
DefinedQueryObserverResult,
|
|
14
14
|
} from '@tanstack/query-core'
|
|
15
15
|
import type { QueryClient } from '@tanstack/query-core'
|
|
16
16
|
|
package/src/useBaseQuery.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import * as React from 'react'
|
|
3
|
-
import { useSyncExternalStore } from './useSyncExternalStore'
|
|
4
3
|
|
|
5
|
-
import type { QueryKey, QueryObserver } from '@tanstack/query-core'
|
|
6
4
|
import { notifyManager } from '@tanstack/query-core'
|
|
5
|
+
import { useSyncExternalStore } from './useSyncExternalStore'
|
|
7
6
|
import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'
|
|
8
7
|
import { useQueryClient } from './QueryClientProvider'
|
|
9
|
-
import type { UseBaseQueryOptions } from './types'
|
|
10
8
|
import { useIsRestoring } from './isRestoring'
|
|
11
9
|
import {
|
|
12
10
|
ensurePreventErrorBoundaryRetry,
|
|
13
11
|
getHasError,
|
|
14
12
|
useClearResetErrorBoundary,
|
|
15
13
|
} from './errorBoundaryUtils'
|
|
16
|
-
import { ensureStaleTime,
|
|
14
|
+
import { ensureStaleTime, fetchOptimistic, shouldSuspend } from './suspense'
|
|
15
|
+
import type { QueryKey, QueryObserver } from '@tanstack/query-core'
|
|
16
|
+
import type { UseBaseQueryOptions } from './types'
|
|
17
17
|
|
|
18
18
|
export function useBaseQuery<
|
|
19
19
|
TQueryFnData,
|