@tanstack/query-core 4.22.4 → 4.24.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-core",
3
- "version": "4.22.4",
3
+ "version": "4.24.3",
4
4
  "description": "The framework agnostic core that powers TanStack Query",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -33,7 +33,6 @@
33
33
  "test:types": "tsc",
34
34
  "test:lib": "jest --config ./jest.config.ts",
35
35
  "test:lib:dev": "pnpm run test:lib --watch",
36
- "test:lib:publish": "pnpm run test:lib --collectCoverage false",
37
36
  "build:types": "tsc --build"
38
37
  }
39
38
  }
@@ -79,6 +79,7 @@ export class MutationCache extends Subscribable<MutationCacheListener> {
79
79
 
80
80
  private mutations: Mutation<any, any, any, any>[]
81
81
  private mutationId: number
82
+ private resuming: Promise<void> | undefined
82
83
 
83
84
  constructor(config?: MutationCacheConfig) {
84
85
  super()
@@ -153,13 +154,21 @@ export class MutationCache extends Subscribable<MutationCacheListener> {
153
154
  }
154
155
 
155
156
  resumePausedMutations(): Promise<void> {
156
- const pausedMutations = this.mutations.filter((x) => x.state.isPaused)
157
- return notifyManager.batch(() =>
158
- pausedMutations.reduce(
159
- (promise, mutation) =>
160
- promise.then(() => mutation.continue().catch(noop)),
161
- Promise.resolve(),
162
- ),
163
- )
157
+ if (!this.resuming) {
158
+ const pausedMutations = this.mutations.filter((x) => x.state.isPaused)
159
+ this.resuming = notifyManager
160
+ .batch(() =>
161
+ pausedMutations.reduce(
162
+ (promise, mutation) =>
163
+ promise.then(() => mutation.continue().catch(noop)),
164
+ Promise.resolve(),
165
+ ),
166
+ )
167
+ .then(() => {
168
+ this.resuming = undefined
169
+ })
170
+ }
171
+
172
+ return this.resuming
164
173
  }
165
174
  }
package/src/query.ts CHANGED
@@ -173,6 +173,7 @@ export class Query<
173
173
  this.queryHash = config.queryHash
174
174
  this.initialState = config.state || getDefaultState(this.options)
175
175
  this.state = this.initialState
176
+ this.scheduleGc()
176
177
  }
177
178
 
178
179
  get meta(): QueryMeta | undefined {
@@ -883,4 +883,28 @@ describe('query', () => {
883
883
 
884
884
  expect(initialDataUpdatedAtSpy).toHaveBeenCalled()
885
885
  })
886
+
887
+ test('queries should be garbage collected even if they never fetched', async () => {
888
+ const key = queryKey()
889
+
890
+ queryClient.setQueryDefaults(key, { cacheTime: 10 })
891
+
892
+ const fn = jest.fn()
893
+
894
+ const unsubscribe = queryClient.getQueryCache().subscribe(fn)
895
+
896
+ queryClient.setQueryData(key, 'data')
897
+
898
+ await waitFor(() =>
899
+ expect(fn).toHaveBeenCalledWith(
900
+ expect.objectContaining({
901
+ type: 'removed',
902
+ }),
903
+ ),
904
+ )
905
+
906
+ expect(queryClient.getQueryCache().findAll()).toHaveLength(0)
907
+
908
+ unsubscribe()
909
+ })
886
910
  })
@@ -8,8 +8,9 @@ import type {
8
8
  QueryFunction,
9
9
  QueryObserverOptions,
10
10
  } from '..'
11
- import { InfiniteQueryObserver, QueryObserver } from '..'
11
+ import { InfiniteQueryObserver, MutationObserver, QueryObserver } from '..'
12
12
  import { focusManager, onlineManager } from '..'
13
+ import { noop } from '../utils'
13
14
 
14
15
  describe('queryClient', () => {
15
16
  let queryClient: QueryClient
@@ -1468,6 +1469,83 @@ describe('queryClient', () => {
1468
1469
  onlineManager.setOnline(undefined)
1469
1470
  })
1470
1471
 
1472
+ test('should resume paused mutations when coming online', async () => {
1473
+ const consoleMock = jest.spyOn(console, 'error')
1474
+ consoleMock.mockImplementation(() => undefined)
1475
+ onlineManager.setOnline(false)
1476
+
1477
+ const observer1 = new MutationObserver(queryClient, {
1478
+ mutationFn: async () => 1,
1479
+ })
1480
+
1481
+ const observer2 = new MutationObserver(queryClient, {
1482
+ mutationFn: async () => 2,
1483
+ })
1484
+ void observer1.mutate().catch(noop)
1485
+ void observer2.mutate().catch(noop)
1486
+
1487
+ await waitFor(() => {
1488
+ expect(observer1.getCurrentResult().isPaused).toBeTruthy()
1489
+ expect(observer2.getCurrentResult().isPaused).toBeTruthy()
1490
+ })
1491
+
1492
+ onlineManager.setOnline(true)
1493
+
1494
+ await waitFor(() => {
1495
+ expect(observer1.getCurrentResult().status).toBe('success')
1496
+ expect(observer1.getCurrentResult().status).toBe('success')
1497
+ })
1498
+
1499
+ onlineManager.setOnline(undefined)
1500
+ })
1501
+
1502
+ test('should resume paused mutations one after the other when invoked manually at the same time', async () => {
1503
+ const consoleMock = jest.spyOn(console, 'error')
1504
+ consoleMock.mockImplementation(() => undefined)
1505
+ onlineManager.setOnline(false)
1506
+
1507
+ const orders: Array<string> = []
1508
+
1509
+ const observer1 = new MutationObserver(queryClient, {
1510
+ mutationFn: async () => {
1511
+ orders.push('1start')
1512
+ await sleep(50)
1513
+ orders.push('1end')
1514
+ return 1
1515
+ },
1516
+ })
1517
+
1518
+ const observer2 = new MutationObserver(queryClient, {
1519
+ mutationFn: async () => {
1520
+ orders.push('2start')
1521
+ await sleep(20)
1522
+ orders.push('2end')
1523
+ return 2
1524
+ },
1525
+ })
1526
+ void observer1.mutate().catch(noop)
1527
+ void observer2.mutate().catch(noop)
1528
+
1529
+ await waitFor(() => {
1530
+ expect(observer1.getCurrentResult().isPaused).toBeTruthy()
1531
+ expect(observer2.getCurrentResult().isPaused).toBeTruthy()
1532
+ })
1533
+
1534
+ onlineManager.setOnline(undefined)
1535
+ void queryClient.resumePausedMutations()
1536
+ await sleep(5)
1537
+ await queryClient.resumePausedMutations()
1538
+
1539
+ await waitFor(() => {
1540
+ expect(observer1.getCurrentResult().status).toBe('success')
1541
+ expect(observer2.getCurrentResult().status).toBe('success')
1542
+ })
1543
+
1544
+ console.log('orders', orders)
1545
+
1546
+ expect(orders).toEqual(['1start', '1end', '2start', '2end'])
1547
+ })
1548
+
1471
1549
  test('should notify queryCache and mutationCache after multiple mounts and single unmount', async () => {
1472
1550
  const testClient = createQueryClient()
1473
1551
  testClient.mount()