@tanstack/query-core 5.0.0-alpha.18 → 5.0.0-alpha.19

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": "5.0.0-alpha.18",
3
+ "version": "5.0.0-alpha.19",
4
4
  "description": "The framework agnostic core that powers TanStack Query",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -64,10 +64,12 @@ export class QueryObserver<
64
64
  TQueryData,
65
65
  TQueryKey
66
66
  >
67
- #previousQueryResult?: QueryObserverResult<TData, TError>
68
67
  #selectError: TError | null
69
68
  #selectFn?: (data: TQueryData) => TData
70
69
  #selectResult?: TData
70
+ // This property keeps track of the last defined query data.
71
+ // It will be used to pass the previous data to the placeholder function between renders.
72
+ #lastDefinedQueryData?: TQueryData
71
73
  #staleTimeoutId?: ReturnType<typeof setTimeout>
72
74
  #refetchIntervalId?: ReturnType<typeof setInterval>
73
75
  #currentRefetchInterval?: number | false
@@ -414,9 +416,6 @@ export class QueryObserver<
414
416
  const queryInitialState = queryChange
415
417
  ? query.state
416
418
  : this.#currentQueryInitialState
417
- const prevQueryResult = queryChange
418
- ? this.#currentResult
419
- : this.#previousQueryResult
420
419
 
421
420
  const { state } = query
422
421
  let { error, errorUpdatedAt, fetchStatus, status } = state
@@ -490,7 +489,7 @@ export class QueryObserver<
490
489
  typeof options.placeholderData === 'function'
491
490
  ? (
492
491
  options.placeholderData as unknown as PlaceholderDataFunction<TQueryData>
493
- )(prevQueryResult?.data as TQueryData | undefined)
492
+ )(this.#lastDefinedQueryData)
494
493
  : options.placeholderData
495
494
  if (options.select && typeof placeholderData !== 'undefined') {
496
495
  try {
@@ -504,7 +503,11 @@ export class QueryObserver<
504
503
 
505
504
  if (typeof placeholderData !== 'undefined') {
506
505
  status = 'success'
507
- data = replaceData(prevResult?.data, placeholderData, options) as TData
506
+ data = replaceData(
507
+ prevResult?.data,
508
+ placeholderData as unknown,
509
+ options,
510
+ ) as TData
508
511
  isPlaceholderData = true
509
512
  }
510
513
  }
@@ -568,6 +571,9 @@ export class QueryObserver<
568
571
  return
569
572
  }
570
573
 
574
+ if (this.#currentResultState.data !== undefined) {
575
+ this.#lastDefinedQueryData = this.#currentResultState.data
576
+ }
571
577
  this.#currentResult = nextResult
572
578
 
573
579
  // Determine which callbacks to trigger
@@ -619,7 +625,6 @@ export class QueryObserver<
619
625
  | undefined
620
626
  this.#currentQuery = query
621
627
  this.#currentQueryInitialState = query.state
622
- this.#previousQueryResult = this.#currentResult
623
628
 
624
629
  if (this.hasListeners()) {
625
630
  prevQuery?.removeObserver(this)
@@ -691,6 +691,61 @@ describe('queryObserver', () => {
691
691
  expect(observer.getCurrentResult().isPlaceholderData).toBe(false)
692
692
  })
693
693
 
694
+ test('should pass the correct previous data to placeholderData function params when select function is used in conjunction', async () => {
695
+ const results: QueryObserverResult[] = []
696
+
697
+ const key1 = queryKey()
698
+ const key2 = queryKey()
699
+
700
+ const data1 = { value: 'data1' }
701
+ const data2 = { value: 'data2' }
702
+
703
+ const observer = new QueryObserver(queryClient, {
704
+ queryKey: key1,
705
+ queryFn: () => data1,
706
+ placeholderData: (prev) => prev,
707
+ select: (data) => data.value,
708
+ })
709
+
710
+ const unsubscribe = observer.subscribe((result) => {
711
+ results.push(result)
712
+ })
713
+
714
+ await sleep(1)
715
+
716
+ observer.setOptions({
717
+ queryKey: key2,
718
+ queryFn: () => data2,
719
+ placeholderData: (prev) => prev,
720
+ select: (data) => data.value,
721
+ })
722
+
723
+ await sleep(1)
724
+ unsubscribe()
725
+
726
+ expect(results.length).toBe(4)
727
+ expect(results[0]).toMatchObject({
728
+ data: undefined,
729
+ status: 'pending',
730
+ fetchStatus: 'fetching',
731
+ }) // Initial fetch
732
+ expect(results[1]).toMatchObject({
733
+ data: 'data1',
734
+ status: 'success',
735
+ fetchStatus: 'idle',
736
+ }) // Successful fetch
737
+ expect(results[2]).toMatchObject({
738
+ data: 'data1',
739
+ status: 'success',
740
+ fetchStatus: 'fetching',
741
+ }) // Fetch for new key, but using previous data as placeholder
742
+ expect(results[3]).toMatchObject({
743
+ data: 'data2',
744
+ status: 'success',
745
+ fetchStatus: 'idle',
746
+ }) // Successful fetch for new key
747
+ })
748
+
694
749
  test('setOptions should notify cache listeners', async () => {
695
750
  const key = queryKey()
696
751