@tanstack/react-query 4.0.5
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/cjs/query-core/build/esm/index.js +3110 -0
- package/build/cjs/query-core/build/esm/index.js.map +1 -0
- package/build/cjs/react-query/src/Hydrate.js +66 -0
- package/build/cjs/react-query/src/Hydrate.js.map +1 -0
- package/build/cjs/react-query/src/QueryClientProvider.js +96 -0
- package/build/cjs/react-query/src/QueryClientProvider.js.map +1 -0
- package/build/cjs/react-query/src/QueryErrorResetBoundary.js +67 -0
- package/build/cjs/react-query/src/QueryErrorResetBoundary.js.map +1 -0
- package/build/cjs/react-query/src/index.js +64 -0
- package/build/cjs/react-query/src/index.js.map +1 -0
- package/build/cjs/react-query/src/isRestoring.js +43 -0
- package/build/cjs/react-query/src/isRestoring.js.map +1 -0
- package/build/cjs/react-query/src/useBaseQuery.js +117 -0
- package/build/cjs/react-query/src/useBaseQuery.js.map +1 -0
- package/build/cjs/react-query/src/useInfiniteQuery.js +24 -0
- package/build/cjs/react-query/src/useInfiniteQuery.js.map +1 -0
- package/build/cjs/react-query/src/useIsFetching.js +50 -0
- package/build/cjs/react-query/src/useIsFetching.js.map +1 -0
- package/build/cjs/react-query/src/useIsMutating.js +50 -0
- package/build/cjs/react-query/src/useIsMutating.js.map +1 -0
- package/build/cjs/react-query/src/useMutation.js +68 -0
- package/build/cjs/react-query/src/useMutation.js.map +1 -0
- package/build/cjs/react-query/src/useQueries.js +71 -0
- package/build/cjs/react-query/src/useQueries.js.map +1 -0
- package/build/cjs/react-query/src/useQuery.js +24 -0
- package/build/cjs/react-query/src/useQuery.js.map +1 -0
- package/build/cjs/react-query/src/utils.js +25 -0
- package/build/cjs/react-query/src/utils.js.map +1 -0
- package/build/esm/index.js +3368 -0
- package/build/esm/index.js.map +1 -0
- package/build/stats-html.html +2689 -0
- package/build/stats.json +666 -0
- package/build/types/packages/query-core/src/focusManager.d.ts +16 -0
- package/build/types/packages/query-core/src/hydration.d.ts +34 -0
- package/build/types/packages/query-core/src/index.d.ts +20 -0
- package/build/types/packages/query-core/src/infiniteQueryBehavior.d.ts +15 -0
- package/build/types/packages/query-core/src/infiniteQueryObserver.d.ts +18 -0
- package/build/types/packages/query-core/src/logger.d.ts +8 -0
- package/build/types/packages/query-core/src/mutation.d.ts +70 -0
- package/build/types/packages/query-core/src/mutationCache.d.ts +52 -0
- package/build/types/packages/query-core/src/mutationObserver.d.ts +23 -0
- package/build/types/packages/query-core/src/notifyManager.d.ts +18 -0
- package/build/types/packages/query-core/src/onlineManager.d.ts +16 -0
- package/build/types/packages/query-core/src/queriesObserver.d.ts +23 -0
- package/build/types/packages/query-core/src/query.d.ts +119 -0
- package/build/types/packages/query-core/src/queryCache.d.ts +59 -0
- package/build/types/packages/query-core/src/queryClient.d.ts +65 -0
- package/build/types/packages/query-core/src/queryObserver.d.ts +61 -0
- package/build/types/packages/query-core/src/removable.d.ts +9 -0
- package/build/types/packages/query-core/src/retryer.d.ts +33 -0
- package/build/types/packages/query-core/src/subscribable.d.ts +10 -0
- package/build/types/packages/query-core/src/types.d.ts +417 -0
- package/build/types/packages/query-core/src/utils.d.ts +99 -0
- package/build/types/packages/react-query/src/Hydrate.d.ts +10 -0
- package/build/types/packages/react-query/src/QueryClientProvider.d.ts +24 -0
- package/build/types/packages/react-query/src/QueryErrorResetBoundary.d.ts +12 -0
- package/build/types/packages/react-query/src/__tests__/Hydrate.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/QueryClientProvider.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/QueryResetErrorBoundary.test.d.ts +6 -0
- package/build/types/packages/react-query/src/__tests__/ssr-hydration.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/ssr.test.d.ts +4 -0
- package/build/types/packages/react-query/src/__tests__/suspense.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useInfiniteQuery.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useIsFetching.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useIsMutating.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useMutation.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQueries.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQuery.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQuery.types.test.d.ts +2 -0
- package/build/types/packages/react-query/src/__tests__/utils.d.ts +8 -0
- package/build/types/packages/react-query/src/index.d.ts +17 -0
- package/build/types/packages/react-query/src/isRestoring.d.ts +3 -0
- package/build/types/packages/react-query/src/reactBatchedUpdates.d.ts +2 -0
- package/build/types/packages/react-query/src/reactBatchedUpdates.native.d.ts +2 -0
- package/build/types/packages/react-query/src/setBatchUpdatesFn.d.ts +1 -0
- package/build/types/packages/react-query/src/types.d.ts +35 -0
- package/build/types/packages/react-query/src/useBaseQuery.d.ts +3 -0
- package/build/types/packages/react-query/src/useInfiniteQuery.d.ts +5 -0
- package/build/types/packages/react-query/src/useIsFetching.d.ts +7 -0
- package/build/types/packages/react-query/src/useIsMutating.d.ts +7 -0
- package/build/types/packages/react-query/src/useMutation.d.ts +6 -0
- package/build/types/packages/react-query/src/useQueries.d.ts +49 -0
- package/build/types/packages/react-query/src/useQuery.d.ts +20 -0
- package/build/types/packages/react-query/src/utils.d.ts +1 -0
- package/build/types/tests/utils.d.ts +24 -0
- package/build/umd/index.development.js +3429 -0
- package/build/umd/index.development.js.map +1 -0
- package/build/umd/index.production.js +22 -0
- package/build/umd/index.production.js.map +1 -0
- package/codemods/v4/key-transformation.js +138 -0
- package/codemods/v4/replace-import-specifier.js +25 -0
- package/codemods/v4/utils/index.js +166 -0
- package/codemods/v4/utils/replacers/key-replacer.js +160 -0
- package/codemods/v4/utils/transformers/query-cache-transformer.js +115 -0
- package/codemods/v4/utils/transformers/query-client-transformer.js +49 -0
- package/codemods/v4/utils/transformers/use-query-like-transformer.js +32 -0
- package/codemods/v4/utils/unprocessable-key-error.js +8 -0
- package/package.json +63 -0
- package/src/Hydrate.tsx +36 -0
- package/src/QueryClientProvider.tsx +90 -0
- package/src/QueryErrorResetBoundary.tsx +52 -0
- package/src/__tests__/Hydrate.test.tsx +247 -0
- package/src/__tests__/QueryClientProvider.test.tsx +275 -0
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +630 -0
- package/src/__tests__/ssr-hydration.test.tsx +274 -0
- package/src/__tests__/ssr.test.tsx +151 -0
- package/src/__tests__/suspense.test.tsx +1015 -0
- package/src/__tests__/useInfiniteQuery.test.tsx +1773 -0
- package/src/__tests__/useIsFetching.test.tsx +274 -0
- package/src/__tests__/useIsMutating.test.tsx +260 -0
- package/src/__tests__/useMutation.test.tsx +1099 -0
- package/src/__tests__/useQueries.test.tsx +1107 -0
- package/src/__tests__/useQuery.test.tsx +5746 -0
- package/src/__tests__/useQuery.types.test.tsx +157 -0
- package/src/__tests__/utils.tsx +45 -0
- package/src/index.ts +29 -0
- package/src/isRestoring.tsx +6 -0
- package/src/reactBatchedUpdates.native.ts +4 -0
- package/src/reactBatchedUpdates.ts +2 -0
- package/src/setBatchUpdatesFn.ts +4 -0
- package/src/types.ts +122 -0
- package/src/useBaseQuery.ts +140 -0
- package/src/useInfiniteQuery.ts +101 -0
- package/src/useIsFetching.ts +39 -0
- package/src/useIsMutating.ts +43 -0
- package/src/useMutation.ts +126 -0
- package/src/useQueries.ts +192 -0
- package/src/useQuery.ts +104 -0
- package/src/utils.ts +11 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { fireEvent, waitFor } from '@testing-library/react'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
createQueryClient,
|
|
7
|
+
queryKey,
|
|
8
|
+
setActTimeout,
|
|
9
|
+
sleep,
|
|
10
|
+
} from '../../../../tests/utils'
|
|
11
|
+
import { renderWithClient } from './utils'
|
|
12
|
+
import { QueryClient, useQuery, useIsFetching, QueryCache } from '..'
|
|
13
|
+
|
|
14
|
+
describe('useIsFetching', () => {
|
|
15
|
+
// See https://github.com/tannerlinsley/react-query/issues/105
|
|
16
|
+
it('should update as queries start and stop fetching', async () => {
|
|
17
|
+
const queryCache = new QueryCache()
|
|
18
|
+
const queryClient = createQueryClient({ queryCache })
|
|
19
|
+
const key = queryKey()
|
|
20
|
+
|
|
21
|
+
function IsFetching() {
|
|
22
|
+
const isFetching = useIsFetching()
|
|
23
|
+
return <div>isFetching: {isFetching}</div>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function Query() {
|
|
27
|
+
const [ready, setReady] = React.useState(false)
|
|
28
|
+
|
|
29
|
+
useQuery(
|
|
30
|
+
key,
|
|
31
|
+
async () => {
|
|
32
|
+
await sleep(50)
|
|
33
|
+
return 'test'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
enabled: ready,
|
|
37
|
+
},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
return <button onClick={() => setReady(true)}>setReady</button>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function Page() {
|
|
44
|
+
return (
|
|
45
|
+
<div>
|
|
46
|
+
<IsFetching />
|
|
47
|
+
<Query />
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { findByText, getByRole } = renderWithClient(queryClient, <Page />)
|
|
53
|
+
|
|
54
|
+
await findByText('isFetching: 0')
|
|
55
|
+
fireEvent.click(getByRole('button', { name: /setReady/i }))
|
|
56
|
+
await findByText('isFetching: 1')
|
|
57
|
+
await findByText('isFetching: 0')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should not update state while rendering', async () => {
|
|
61
|
+
const queryCache = new QueryCache()
|
|
62
|
+
const queryClient = createQueryClient({ queryCache })
|
|
63
|
+
|
|
64
|
+
const key1 = queryKey()
|
|
65
|
+
const key2 = queryKey()
|
|
66
|
+
|
|
67
|
+
const isFetchings: number[] = []
|
|
68
|
+
|
|
69
|
+
function IsFetching() {
|
|
70
|
+
const isFetching = useIsFetching()
|
|
71
|
+
isFetchings.push(isFetching)
|
|
72
|
+
return null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function FirstQuery() {
|
|
76
|
+
useQuery(key1, async () => {
|
|
77
|
+
await sleep(100)
|
|
78
|
+
return 'data'
|
|
79
|
+
})
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function SecondQuery() {
|
|
84
|
+
useQuery(key2, async () => {
|
|
85
|
+
await sleep(100)
|
|
86
|
+
return 'data'
|
|
87
|
+
})
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function Page() {
|
|
92
|
+
const [renderSecond, setRenderSecond] = React.useState(false)
|
|
93
|
+
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
setActTimeout(() => {
|
|
96
|
+
setRenderSecond(true)
|
|
97
|
+
}, 50)
|
|
98
|
+
}, [])
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<>
|
|
102
|
+
<IsFetching />
|
|
103
|
+
<FirstQuery />
|
|
104
|
+
{renderSecond && <SecondQuery />}
|
|
105
|
+
</>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
renderWithClient(queryClient, <Page />)
|
|
110
|
+
await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0]))
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('should be able to filter', async () => {
|
|
114
|
+
const queryClient = createQueryClient()
|
|
115
|
+
const key1 = queryKey()
|
|
116
|
+
const key2 = queryKey()
|
|
117
|
+
|
|
118
|
+
const isFetchings: number[] = []
|
|
119
|
+
|
|
120
|
+
function One() {
|
|
121
|
+
useQuery(key1, async () => {
|
|
122
|
+
await sleep(10)
|
|
123
|
+
return 'test'
|
|
124
|
+
})
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function Two() {
|
|
129
|
+
useQuery(key2, async () => {
|
|
130
|
+
await sleep(20)
|
|
131
|
+
return 'test'
|
|
132
|
+
})
|
|
133
|
+
return null
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function Page() {
|
|
137
|
+
const [started, setStarted] = React.useState(false)
|
|
138
|
+
const isFetching = useIsFetching(key1)
|
|
139
|
+
|
|
140
|
+
isFetchings.push(isFetching)
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<div>
|
|
144
|
+
<button onClick={() => setStarted(true)}>setStarted</button>
|
|
145
|
+
<div>isFetching: {isFetching}</div>
|
|
146
|
+
{started ? (
|
|
147
|
+
<>
|
|
148
|
+
<One />
|
|
149
|
+
<Two />
|
|
150
|
+
</>
|
|
151
|
+
) : null}
|
|
152
|
+
</div>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { findByText, getByRole } = renderWithClient(queryClient, <Page />)
|
|
157
|
+
|
|
158
|
+
await findByText('isFetching: 0')
|
|
159
|
+
fireEvent.click(getByRole('button', { name: /setStarted/i }))
|
|
160
|
+
await findByText('isFetching: 1')
|
|
161
|
+
await findByText('isFetching: 0')
|
|
162
|
+
// at no point should we have isFetching: 2
|
|
163
|
+
expect(isFetchings).toEqual(expect.not.arrayContaining([2]))
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
describe('with custom context', () => {
|
|
167
|
+
it('should update as queries start and stop fetching', async () => {
|
|
168
|
+
const context = React.createContext<QueryClient | undefined>(undefined)
|
|
169
|
+
|
|
170
|
+
const queryCache = new QueryCache()
|
|
171
|
+
const queryClient = createQueryClient({ queryCache })
|
|
172
|
+
const key = queryKey()
|
|
173
|
+
|
|
174
|
+
function Page() {
|
|
175
|
+
const [ready, setReady] = React.useState(false)
|
|
176
|
+
|
|
177
|
+
const isFetching = useIsFetching(undefined, { context: context })
|
|
178
|
+
|
|
179
|
+
useQuery(
|
|
180
|
+
key,
|
|
181
|
+
async () => {
|
|
182
|
+
await sleep(50)
|
|
183
|
+
return 'test'
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
enabled: ready,
|
|
187
|
+
context,
|
|
188
|
+
},
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<div>
|
|
193
|
+
<div>isFetching: {isFetching}</div>
|
|
194
|
+
<button onClick={() => setReady(true)}>setReady</button>
|
|
195
|
+
</div>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const { findByText, getByRole } = renderWithClient(
|
|
200
|
+
queryClient,
|
|
201
|
+
<Page />,
|
|
202
|
+
{
|
|
203
|
+
context,
|
|
204
|
+
},
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
await findByText('isFetching: 0')
|
|
208
|
+
fireEvent.click(getByRole('button', { name: /setReady/i }))
|
|
209
|
+
await findByText('isFetching: 1')
|
|
210
|
+
await findByText('isFetching: 0')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('should throw if the context is not passed to useIsFetching', async () => {
|
|
214
|
+
const context = React.createContext<QueryClient | undefined>(undefined)
|
|
215
|
+
|
|
216
|
+
const queryCache = new QueryCache()
|
|
217
|
+
const queryClient = createQueryClient({ queryCache })
|
|
218
|
+
const key = queryKey()
|
|
219
|
+
|
|
220
|
+
function Page() {
|
|
221
|
+
const isFetching = useIsFetching()
|
|
222
|
+
|
|
223
|
+
useQuery(key, async () => 'test', {
|
|
224
|
+
enabled: true,
|
|
225
|
+
context,
|
|
226
|
+
useErrorBoundary: true,
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<div>
|
|
231
|
+
<div>isFetching: {isFetching}</div>
|
|
232
|
+
</div>
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const rendered = renderWithClient(
|
|
237
|
+
queryClient,
|
|
238
|
+
<ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
|
|
239
|
+
<Page />
|
|
240
|
+
</ErrorBoundary>,
|
|
241
|
+
{
|
|
242
|
+
context,
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should show the correct fetching state when mounted after a query', async () => {
|
|
251
|
+
const queryClient = createQueryClient()
|
|
252
|
+
const key = queryKey()
|
|
253
|
+
|
|
254
|
+
function Page() {
|
|
255
|
+
useQuery(key, async () => {
|
|
256
|
+
await sleep(10)
|
|
257
|
+
return 'test'
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
const isFetching = useIsFetching()
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<div>
|
|
264
|
+
<div>isFetching: {isFetching}</div>
|
|
265
|
+
</div>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
270
|
+
|
|
271
|
+
await rendered.findByText('isFetching: 1')
|
|
272
|
+
await rendered.findByText('isFetching: 0')
|
|
273
|
+
})
|
|
274
|
+
})
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { waitFor, fireEvent } from '@testing-library/react'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { useIsMutating } from '../useIsMutating'
|
|
4
|
+
import { useMutation } from '../useMutation'
|
|
5
|
+
import {
|
|
6
|
+
createQueryClient,
|
|
7
|
+
setActTimeout,
|
|
8
|
+
sleep,
|
|
9
|
+
} from '../../../../tests/utils'
|
|
10
|
+
|
|
11
|
+
import { renderWithClient } from './utils'
|
|
12
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
13
|
+
import { QueryClient } from '@tanstack/query-core'
|
|
14
|
+
import * as MutationCacheModule from '../../../query-core/src/mutationCache'
|
|
15
|
+
|
|
16
|
+
describe('useIsMutating', () => {
|
|
17
|
+
it('should return the number of fetching mutations', async () => {
|
|
18
|
+
const isMutatings: number[] = []
|
|
19
|
+
const queryClient = createQueryClient()
|
|
20
|
+
|
|
21
|
+
function IsMutating() {
|
|
22
|
+
const isMutating = useIsMutating()
|
|
23
|
+
isMutatings.push(isMutating)
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function Mutations() {
|
|
28
|
+
const { mutate: mutate1 } = useMutation(['mutation1'], async () => {
|
|
29
|
+
await sleep(150)
|
|
30
|
+
return 'data'
|
|
31
|
+
})
|
|
32
|
+
const { mutate: mutate2 } = useMutation(['mutation2'], async () => {
|
|
33
|
+
await sleep(50)
|
|
34
|
+
return 'data'
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
React.useEffect(() => {
|
|
38
|
+
mutate1()
|
|
39
|
+
setActTimeout(() => {
|
|
40
|
+
mutate2()
|
|
41
|
+
}, 50)
|
|
42
|
+
}, [mutate1, mutate2])
|
|
43
|
+
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Page() {
|
|
48
|
+
return (
|
|
49
|
+
<div>
|
|
50
|
+
<IsMutating />
|
|
51
|
+
<Mutations />
|
|
52
|
+
</div>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
renderWithClient(queryClient, <Page />)
|
|
57
|
+
await waitFor(() => expect(isMutatings).toEqual([0, 1, 2, 1, 0]))
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should filter correctly by mutationKey', async () => {
|
|
61
|
+
const isMutatings: number[] = []
|
|
62
|
+
const queryClient = createQueryClient()
|
|
63
|
+
|
|
64
|
+
function IsMutating() {
|
|
65
|
+
const isMutating = useIsMutating(['mutation1'])
|
|
66
|
+
isMutatings.push(isMutating)
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function Page() {
|
|
71
|
+
const { mutate: mutate1 } = useMutation(['mutation1'], async () => {
|
|
72
|
+
await sleep(100)
|
|
73
|
+
return 'data'
|
|
74
|
+
})
|
|
75
|
+
const { mutate: mutate2 } = useMutation(['mutation2'], async () => {
|
|
76
|
+
await sleep(100)
|
|
77
|
+
return 'data'
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
React.useEffect(() => {
|
|
81
|
+
mutate1()
|
|
82
|
+
mutate2()
|
|
83
|
+
}, [mutate1, mutate2])
|
|
84
|
+
|
|
85
|
+
return <IsMutating />
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
renderWithClient(queryClient, <Page />)
|
|
89
|
+
await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0]))
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should filter correctly by predicate', async () => {
|
|
93
|
+
const isMutatings: number[] = []
|
|
94
|
+
const queryClient = createQueryClient()
|
|
95
|
+
|
|
96
|
+
function IsMutating() {
|
|
97
|
+
const isMutating = useIsMutating({
|
|
98
|
+
predicate: (mutation) =>
|
|
99
|
+
mutation.options.mutationKey?.[0] === 'mutation1',
|
|
100
|
+
})
|
|
101
|
+
isMutatings.push(isMutating)
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function Page() {
|
|
106
|
+
const { mutate: mutate1 } = useMutation(['mutation1'], async () => {
|
|
107
|
+
await sleep(100)
|
|
108
|
+
return 'data'
|
|
109
|
+
})
|
|
110
|
+
const { mutate: mutate2 } = useMutation(['mutation2'], async () => {
|
|
111
|
+
await sleep(100)
|
|
112
|
+
return 'data'
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
React.useEffect(() => {
|
|
116
|
+
mutate1()
|
|
117
|
+
mutate2()
|
|
118
|
+
}, [mutate1, mutate2])
|
|
119
|
+
|
|
120
|
+
return <IsMutating />
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
renderWithClient(queryClient, <Page />)
|
|
124
|
+
await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0]))
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('should not change state if unmounted', async () => {
|
|
128
|
+
// We have to mock the MutationCache to not unsubscribe
|
|
129
|
+
// the listener when the component is unmounted
|
|
130
|
+
class MutationCacheMock extends MutationCacheModule.MutationCache {
|
|
131
|
+
subscribe(listener: any) {
|
|
132
|
+
super.subscribe(listener)
|
|
133
|
+
return () => void 0
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const MutationCacheSpy = jest
|
|
138
|
+
.spyOn(MutationCacheModule, 'MutationCache')
|
|
139
|
+
.mockImplementation((fn) => {
|
|
140
|
+
return new MutationCacheMock(fn)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const queryClient = createQueryClient()
|
|
144
|
+
|
|
145
|
+
function IsMutating() {
|
|
146
|
+
useIsMutating()
|
|
147
|
+
return null
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function Page() {
|
|
151
|
+
const [mounted, setMounted] = React.useState(true)
|
|
152
|
+
const { mutate: mutate1 } = useMutation(['mutation1'], async () => {
|
|
153
|
+
await sleep(10)
|
|
154
|
+
return 'data'
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
React.useEffect(() => {
|
|
158
|
+
mutate1()
|
|
159
|
+
}, [mutate1])
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<div>
|
|
163
|
+
<button onClick={() => setMounted(false)}>unmount</button>
|
|
164
|
+
{mounted && <IsMutating />}
|
|
165
|
+
</div>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const { getByText } = renderWithClient(queryClient, <Page />)
|
|
170
|
+
fireEvent.click(getByText('unmount'))
|
|
171
|
+
|
|
172
|
+
// Should not display the console error
|
|
173
|
+
// "Warning: Can't perform a React state update on an unmounted component"
|
|
174
|
+
|
|
175
|
+
await sleep(20)
|
|
176
|
+
MutationCacheSpy.mockRestore()
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
describe('with custom context', () => {
|
|
180
|
+
it('should return the number of fetching mutations', async () => {
|
|
181
|
+
const context = React.createContext<QueryClient | undefined>(undefined)
|
|
182
|
+
|
|
183
|
+
const isMutatings: number[] = []
|
|
184
|
+
const queryClient = new QueryClient()
|
|
185
|
+
|
|
186
|
+
function IsMutating() {
|
|
187
|
+
const isMutating = useIsMutating(undefined, { context })
|
|
188
|
+
isMutatings.push(isMutating)
|
|
189
|
+
return null
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function Page() {
|
|
193
|
+
const { mutate: mutate1 } = useMutation(
|
|
194
|
+
['mutation1'],
|
|
195
|
+
async () => {
|
|
196
|
+
await sleep(150)
|
|
197
|
+
return 'data'
|
|
198
|
+
},
|
|
199
|
+
{ context },
|
|
200
|
+
)
|
|
201
|
+
const { mutate: mutate2 } = useMutation(
|
|
202
|
+
['mutation2'],
|
|
203
|
+
async () => {
|
|
204
|
+
await sleep(50)
|
|
205
|
+
return 'data'
|
|
206
|
+
},
|
|
207
|
+
{ context },
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
React.useEffect(() => {
|
|
211
|
+
mutate1()
|
|
212
|
+
setActTimeout(() => {
|
|
213
|
+
mutate2()
|
|
214
|
+
}, 50)
|
|
215
|
+
}, [mutate1, mutate2])
|
|
216
|
+
|
|
217
|
+
return <IsMutating />
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
renderWithClient(queryClient, <Page />, { context })
|
|
221
|
+
await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0]))
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
it('should throw if the context is not passed to useIsMutating', async () => {
|
|
225
|
+
const context = React.createContext<QueryClient | undefined>(undefined)
|
|
226
|
+
|
|
227
|
+
const isMutatings: number[] = []
|
|
228
|
+
const queryClient = new QueryClient()
|
|
229
|
+
|
|
230
|
+
function IsMutating() {
|
|
231
|
+
const isMutating = useIsMutating(undefined)
|
|
232
|
+
isMutatings.push(isMutating)
|
|
233
|
+
return null
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function Page() {
|
|
237
|
+
const { mutate } = useMutation(['mutation'], async () => 'data', {
|
|
238
|
+
useErrorBoundary: true,
|
|
239
|
+
context,
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
React.useEffect(() => {
|
|
243
|
+
mutate()
|
|
244
|
+
}, [mutate])
|
|
245
|
+
|
|
246
|
+
return <IsMutating />
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const rendered = renderWithClient(
|
|
250
|
+
queryClient,
|
|
251
|
+
<ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
|
|
252
|
+
<Page />
|
|
253
|
+
</ErrorBoundary>,
|
|
254
|
+
{ context },
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
})
|