@tanstack/react-query 4.29.19 → 4.29.23

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/react-query",
3
- "version": "4.29.19",
3
+ "version": "4.29.23",
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.29.19"
50
+ "@tanstack/query-core": "4.29.23"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
@@ -914,17 +914,15 @@ describe('useQuery', () => {
914
914
  // required to make sure no additional renders are happening after data is successfully fetched for the second time
915
915
  await sleep(100)
916
916
 
917
- expect(states.length).toBe(5)
917
+ expect(states.length).toBe(4)
918
918
  // First load
919
919
  expect(states[0]).toMatchObject({ isLoading: true, isSuccess: false })
920
920
  // First success
921
921
  expect(states[1]).toMatchObject({ isLoading: false, isSuccess: true })
922
922
  // Remove
923
923
  expect(states[2]).toMatchObject({ isLoading: true, isSuccess: false })
924
- // Hook state update
925
- expect(states[3]).toMatchObject({ isLoading: true, isSuccess: false })
926
924
  // Second success
927
- expect(states[4]).toMatchObject({ isLoading: false, isSuccess: true })
925
+ expect(states[3]).toMatchObject({ isLoading: false, isSuccess: true })
928
926
  })
929
927
 
930
928
  it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {
@@ -3650,6 +3648,7 @@ describe('useQuery', () => {
3650
3648
  )
3651
3649
  act(() => setPrefetched(true))
3652
3650
  }
3651
+
3653
3652
  prefetch()
3654
3653
  }, [])
3655
3654
 
@@ -5879,6 +5878,7 @@ describe('useQuery', () => {
5879
5878
  </div>
5880
5879
  )
5881
5880
  }
5881
+
5882
5882
  const rendered = renderWithClient(queryClient, <Page />)
5883
5883
  const fetchBtn = rendered.getByRole('button', { name: 'refetch' })
5884
5884
  await waitFor(() => rendered.getByText('data: 1'))
@@ -5916,8 +5916,132 @@ describe('useQuery', () => {
5916
5916
  </div>
5917
5917
  )
5918
5918
  }
5919
+
5919
5920
  const rendered = renderWithClient(queryClient, <Page />)
5920
5921
  await waitFor(() => rendered.getByText('status: success'))
5921
5922
  await waitFor(() => rendered.getByText('data: 1'))
5922
5923
  })
5924
+ it('should reuse same data object reference when queryKey changes back to some cached data', async () => {
5925
+ const spy = jest.fn()
5926
+ const key = queryKey()
5927
+
5928
+ async function fetchNumber(id: number) {
5929
+ await sleep(5)
5930
+ return { numbers: { current: { id } } }
5931
+ }
5932
+ function Test() {
5933
+ const [id, setId] = React.useState(1)
5934
+
5935
+ const { data } = useQuery({
5936
+ select: selector,
5937
+ queryKey: [key, 'user', id],
5938
+ queryFn: () => fetchNumber(id),
5939
+ })
5940
+
5941
+ React.useEffect(() => {
5942
+ spy(data)
5943
+ }, [data])
5944
+
5945
+ return (
5946
+ <div>
5947
+ <button name="1" onClick={() => setId(1)}>
5948
+ 1
5949
+ </button>
5950
+ <button name="2" onClick={() => setId(2)}>
5951
+ 2
5952
+ </button>
5953
+ <span>Rendered Id: {data?.id}</span>
5954
+ </div>
5955
+ )
5956
+ }
5957
+
5958
+ function selector(data: any) {
5959
+ return data.numbers.current
5960
+ }
5961
+
5962
+ const rendered = renderWithClient(queryClient, <Test />)
5963
+ expect(spy).toHaveBeenCalledTimes(1)
5964
+
5965
+ spy.mockClear()
5966
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
5967
+ expect(spy).toHaveBeenCalledTimes(1)
5968
+
5969
+ spy.mockClear()
5970
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
5971
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
5972
+ expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
5973
+
5974
+ spy.mockClear()
5975
+ fireEvent.click(rendered.getByRole('button', { name: /1/ }))
5976
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
5977
+ expect(spy).toHaveBeenCalledTimes(1)
5978
+
5979
+ spy.mockClear()
5980
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
5981
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
5982
+ expect(spy).toHaveBeenCalledTimes(1)
5983
+ })
5984
+ it('should reuse same data object reference when queryKey changes and placeholderData is present', async () => {
5985
+ const spy = jest.fn()
5986
+ const key = queryKey()
5987
+
5988
+ async function fetchNumber(id: number) {
5989
+ await sleep(5)
5990
+ return { numbers: { current: { id } } }
5991
+ }
5992
+ function Test() {
5993
+ const [id, setId] = React.useState(1)
5994
+
5995
+ const { data } = useQuery({
5996
+ select: selector,
5997
+ queryKey: [key, 'user', id],
5998
+ queryFn: () => fetchNumber(id),
5999
+ placeholderData: { numbers: { current: { id: 99 } } },
6000
+ })
6001
+
6002
+ React.useEffect(() => {
6003
+ spy(data)
6004
+ }, [data])
6005
+
6006
+ return (
6007
+ <div>
6008
+ <button name="1" onClick={() => setId(1)}>
6009
+ 1
6010
+ </button>
6011
+ <button name="2" onClick={() => setId(2)}>
6012
+ 2
6013
+ </button>
6014
+ <span>Rendered Id: {data?.id}</span>
6015
+ </div>
6016
+ )
6017
+ }
6018
+
6019
+ function selector(data: any) {
6020
+ return data.numbers.current
6021
+ }
6022
+
6023
+ const rendered = renderWithClient(queryClient, <Test />)
6024
+ expect(spy).toHaveBeenCalledTimes(1)
6025
+
6026
+ spy.mockClear()
6027
+ await waitFor(() => rendered.getByText('Rendered Id: 99'))
6028
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
6029
+ expect(spy).toHaveBeenCalledTimes(1)
6030
+
6031
+ spy.mockClear()
6032
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6033
+ await waitFor(() => rendered.getByText('Rendered Id: 99'))
6034
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
6035
+ expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
6036
+
6037
+ spy.mockClear()
6038
+ fireEvent.click(rendered.getByRole('button', { name: /1/ }))
6039
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
6040
+ expect(spy).toHaveBeenCalledTimes(1)
6041
+
6042
+ spy.mockClear()
6043
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6044
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
6045
+ expect(spy).toHaveBeenCalledTimes(1)
6046
+ })
5923
6047
  })