@@ -914,17 +914,15 @@ describe('useQuery', () => {
914914 // required to make sure no additional renders are happening after data is successfully fetched for the second time
915915 await sleep ( 100 )
916916
917- expect ( states . length ) . toBe ( 5 )
917+ expect ( states . length ) . toBe ( 4 )
918918 // First load
919919 expect ( states [ 0 ] ) . toMatchObject ( { isLoading : true , isSuccess : false } )
920920 // First success
921921 expect ( states [ 1 ] ) . toMatchObject ( { isLoading : false , isSuccess : true } )
922922 // Remove
923923 expect ( states [ 2 ] ) . toMatchObject ( { isLoading : true , isSuccess : false } )
924- // Hook state update
925- expect ( states [ 3 ] ) . toMatchObject ( { isLoading : true , isSuccess : false } )
926924 // Second success
927- expect ( states [ 4 ] ) . toMatchObject ( { isLoading : false , isSuccess : true } )
925+ expect ( states [ 3 ] ) . toMatchObject ( { isLoading : false , isSuccess : true } )
928926 } )
929927
930928 it ( 'should fetch when refetchOnMount is false and nothing has been fetched yet' , async ( ) => {
@@ -3650,6 +3648,7 @@ describe('useQuery', () => {
36503648 )
36513649 act ( ( ) => setPrefetched ( true ) )
36523650 }
3651+
36533652 prefetch ( )
36543653 } , [ ] )
36553654
@@ -5879,6 +5878,7 @@ describe('useQuery', () => {
58795878 </ div >
58805879 )
58815880 }
5881+
58825882 const rendered = renderWithClient ( queryClient , < Page /> )
58835883 const fetchBtn = rendered . getByRole ( 'button' , { name : 'refetch' } )
58845884 await waitFor ( ( ) => rendered . getByText ( 'data: 1' ) )
@@ -5916,8 +5916,132 @@ describe('useQuery', () => {
59165916 </ div >
59175917 )
59185918 }
5919+
59195920 const rendered = renderWithClient ( queryClient , < Page /> )
59205921 await waitFor ( ( ) => rendered . getByText ( 'status: success' ) )
59215922 await waitFor ( ( ) => rendered . getByText ( 'data: 1' ) )
59225923 } )
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+ } )
59236047} )
0 commit comments