@@ -1386,6 +1386,252 @@ describe('dehydration and rehydration', () => {
13861386 await originalPromise
13871387 } )
13881388
1389+ it ( 'should preserve queryType for infinite queries during hydration' , async ( ) => {
1390+ const queryCache = new QueryCache ( )
1391+ const queryClient = new QueryClient ( { queryCache } )
1392+
1393+ await vi . waitFor ( ( ) =>
1394+ queryClient . prefetchInfiniteQuery ( {
1395+ queryKey : [ 'infinite' ] ,
1396+ queryFn : async ( { pageParam } ) =>
1397+ sleep ( 0 ) . then ( ( ) => ( {
1398+ items : [ `page-${ pageParam } ` ] ,
1399+ nextCursor : pageParam + 1 ,
1400+ } ) ) ,
1401+ initialPageParam : 0 ,
1402+ getNextPageParam : ( lastPage : {
1403+ items : Array < string >
1404+ nextCursor : number
1405+ } ) => lastPage . nextCursor ,
1406+ } ) ,
1407+ )
1408+
1409+ const dehydrated = dehydrate ( queryClient )
1410+
1411+ const infiniteQueryState = dehydrated . queries . find (
1412+ ( q ) => q . queryKey [ 0 ] === 'infinite' ,
1413+ )
1414+ expect ( infiniteQueryState ?. queryType ) . toBe ( 'infinite' )
1415+
1416+ const hydrationCache = new QueryCache ( )
1417+ const hydrationClient = new QueryClient ( { queryCache : hydrationCache } )
1418+ hydrate ( hydrationClient , dehydrated )
1419+
1420+ const hydratedQuery = hydrationCache . find ( { queryKey : [ 'infinite' ] } )
1421+ expect ( hydratedQuery ?. state . data ) . toBeDefined ( )
1422+ expect ( hydratedQuery ?. state . data ) . toHaveProperty ( 'pages' )
1423+ expect ( hydratedQuery ?. state . data ) . toHaveProperty ( 'pageParams' )
1424+ expect ( ( hydratedQuery ?. state . data as any ) . pages ) . toHaveLength ( 1 )
1425+ } )
1426+
1427+ it ( 'should attach infiniteQueryBehavior during hydration' , async ( ) => {
1428+ const queryCache = new QueryCache ( )
1429+ const queryClient = new QueryClient ( { queryCache } )
1430+
1431+ await vi . waitFor ( ( ) =>
1432+ queryClient . prefetchInfiniteQuery ( {
1433+ queryKey : [ 'infinite-with-behavior' ] ,
1434+ queryFn : async ( { pageParam } ) =>
1435+ sleep ( 0 ) . then ( ( ) => ( {
1436+ data : `page-${ pageParam } ` ,
1437+ next : pageParam + 1 ,
1438+ } ) ) ,
1439+ initialPageParam : 0 ,
1440+ getNextPageParam : ( lastPage : { data : string ; next : number } ) =>
1441+ lastPage . next ,
1442+ } ) ,
1443+ )
1444+
1445+ const dehydrated = dehydrate ( queryClient )
1446+
1447+ const hydrationCache = new QueryCache ( )
1448+ const hydrationClient = new QueryClient ( { queryCache : hydrationCache } )
1449+ hydrate ( hydrationClient , dehydrated )
1450+
1451+ const result = await vi . waitFor ( ( ) =>
1452+ hydrationClient . fetchInfiniteQuery ( {
1453+ queryKey : [ 'infinite-with-behavior' ] ,
1454+ queryFn : async ( { pageParam } ) =>
1455+ sleep ( 0 ) . then ( ( ) => ( {
1456+ data : `page-${ pageParam } ` ,
1457+ next : pageParam + 1 ,
1458+ } ) ) ,
1459+ initialPageParam : 0 ,
1460+ getNextPageParam : ( lastPage : { data : string ; next : number } ) =>
1461+ lastPage . next ,
1462+ } ) ,
1463+ )
1464+
1465+ expect ( result . pages ) . toHaveLength ( 1 )
1466+ expect ( result . pageParams ) . toHaveLength ( 1 )
1467+ } )
1468+
1469+ it ( 'should restore infinite query type through dehydrate and hydrate cycle' , async ( ) => {
1470+ const serverClient = new QueryClient ( { queryCache : new QueryCache ( ) } )
1471+
1472+ await vi . waitFor ( ( ) =>
1473+ serverClient . prefetchInfiniteQuery ( {
1474+ queryKey : [ 'infinite-type-restore' ] ,
1475+ queryFn : async ( { pageParam } ) =>
1476+ sleep ( 0 ) . then ( ( ) => ( {
1477+ items : [ `item-${ pageParam } ` ] ,
1478+ next : pageParam + 1 ,
1479+ } ) ) ,
1480+ initialPageParam : 0 ,
1481+ getNextPageParam : ( lastPage : { items : Array < string > ; next : number } ) =>
1482+ lastPage . next ,
1483+ } ) ,
1484+ )
1485+
1486+ const dehydrated = dehydrate ( serverClient )
1487+
1488+ const dehydratedQuery = dehydrated . queries . find (
1489+ ( q ) => q . queryKey [ 0 ] === 'infinite-type-restore' ,
1490+ )
1491+ expect ( dehydratedQuery ?. queryType ) . toBe ( 'infinite' )
1492+
1493+ const clientCache = new QueryCache ( )
1494+ const clientClient = new QueryClient ( { queryCache : clientCache } )
1495+ hydrate ( clientClient , dehydrated )
1496+
1497+ const hydratedQuery = clientCache . find ( {
1498+ queryKey : [ 'infinite-type-restore' ] ,
1499+ } )
1500+ expect ( hydratedQuery ?. queryType ) . toBe ( 'infinite' )
1501+ } )
1502+
1503+ it ( 'should preserve pages structure when refetching infinite query after hydration' , async ( ) => {
1504+ const serverClient = new QueryClient ( { queryCache : new QueryCache ( ) } )
1505+
1506+ await vi . waitFor ( ( ) =>
1507+ serverClient . prefetchInfiniteQuery ( {
1508+ queryKey : [ 'refetch' ] ,
1509+ queryFn : async ( { pageParam } ) =>
1510+ sleep ( 0 ) . then ( ( ) => ( {
1511+ items : [ `page-${ pageParam } ` ] ,
1512+ next : pageParam + 1 ,
1513+ } ) ) ,
1514+ initialPageParam : 0 ,
1515+ getNextPageParam : ( lastPage : { items : Array < string > ; next : number } ) =>
1516+ lastPage . next ,
1517+ } ) ,
1518+ )
1519+
1520+ const dehydrated = dehydrate ( serverClient )
1521+
1522+ const clientCache = new QueryCache ( )
1523+ const clientClient = new QueryClient ( { queryCache : clientCache } )
1524+ hydrate ( clientClient , dehydrated )
1525+
1526+ const beforeRefetch = clientClient . getQueryData < {
1527+ pages : Array < { items : Array < string > ; next : number } >
1528+ pageParams : Array < unknown >
1529+ } > ( [ 'refetch' ] )
1530+ expect ( beforeRefetch ?. pages ) . toHaveLength ( 1 )
1531+ expect ( beforeRefetch ?. pageParams ) . toHaveLength ( 1 )
1532+
1533+ const result = await vi . waitFor ( ( ) =>
1534+ clientClient . fetchInfiniteQuery ( {
1535+ queryKey : [ 'refetch' ] ,
1536+ queryFn : async ( { pageParam } ) =>
1537+ sleep ( 0 ) . then ( ( ) => ( {
1538+ items : [ `page-${ pageParam } ` ] ,
1539+ next : pageParam + 1 ,
1540+ } ) ) ,
1541+ initialPageParam : 0 ,
1542+ getNextPageParam : ( lastPage : { items : Array < string > ; next : number } ) =>
1543+ lastPage . next ,
1544+ } ) ,
1545+ )
1546+
1547+ expect ( result ) . toHaveProperty ( 'pages' )
1548+ expect ( result ) . toHaveProperty ( 'pageParams' )
1549+ expect ( Array . isArray ( result . pages ) ) . toBe ( true )
1550+ expect ( result . pages ) . toHaveLength ( 1 )
1551+ expect ( result . pages [ 0 ] ) . toHaveProperty ( 'items' )
1552+ } )
1553+
1554+ it ( 'should retain infinite query type after subsequent setOptions calls' , async ( ) => {
1555+ const serverClient = new QueryClient ( { queryCache : new QueryCache ( ) } )
1556+
1557+ await vi . waitFor ( ( ) =>
1558+ serverClient . prefetchInfiniteQuery ( {
1559+ queryKey : [ 'infinite-setoptions-guard' ] ,
1560+ queryFn : async ( { pageParam } ) =>
1561+ sleep ( 0 ) . then ( ( ) => ( {
1562+ data : `p${ pageParam } ` ,
1563+ next : pageParam + 1 ,
1564+ } ) ) ,
1565+ initialPageParam : 0 ,
1566+ getNextPageParam : ( lastPage : { data : string ; next : number } ) =>
1567+ lastPage . next ,
1568+ } ) ,
1569+ )
1570+
1571+ const dehydrated = dehydrate ( serverClient )
1572+
1573+ const clientCache = new QueryCache ( )
1574+ const clientClient = new QueryClient ( { queryCache : clientCache } )
1575+ hydrate ( clientClient , dehydrated )
1576+
1577+ const query = clientCache . find ( { queryKey : [ 'infinite-setoptions-guard' ] } ) !
1578+ expect ( query . queryType ) . toBe ( 'infinite' )
1579+
1580+ query . setOptions ( { queryKey : [ 'infinite-setoptions-guard' ] } )
1581+ expect ( query . queryType ) . toBe ( 'infinite' )
1582+ } )
1583+
1584+ it ( 'should restore all pages when refetching multi-page infinite query after hydration' , async ( ) => {
1585+ const serverClient = new QueryClient ( { queryCache : new QueryCache ( ) } )
1586+
1587+ await vi . waitFor ( ( ) =>
1588+ serverClient . prefetchInfiniteQuery ( {
1589+ queryKey : [ 'infinite-multipage-restore' ] ,
1590+ queryFn : async ( { pageParam } ) =>
1591+ sleep ( 0 ) . then ( ( ) => ( {
1592+ items : [ `item-${ pageParam } ` ] ,
1593+ next : pageParam + 1 ,
1594+ } ) ) ,
1595+ initialPageParam : 0 ,
1596+ pages : 2 ,
1597+ getNextPageParam : ( lastPage : { items : Array < string > ; next : number } ) =>
1598+ lastPage . next ,
1599+ } ) ,
1600+ )
1601+
1602+ const dehydrated = dehydrate ( serverClient )
1603+
1604+ const clientCache = new QueryCache ( )
1605+ const clientClient = new QueryClient ( { queryCache : clientCache } )
1606+ hydrate ( clientClient , dehydrated )
1607+
1608+ const beforeRefetch = clientClient . getQueryData < {
1609+ pages : Array < unknown >
1610+ pageParams : Array < unknown >
1611+ } > ( [ 'infinite-multipage-restore' ] )
1612+ expect ( beforeRefetch ?. pages ) . toHaveLength ( 2 )
1613+
1614+ const result = await vi . waitFor ( ( ) =>
1615+ clientClient . fetchInfiniteQuery ( {
1616+ queryKey : [ 'infinite-multipage-restore' ] ,
1617+ queryFn : async ( { pageParam } ) =>
1618+ sleep ( 0 ) . then ( ( ) => ( {
1619+ items : [ `item-${ pageParam } ` ] ,
1620+ next : pageParam + 1 ,
1621+ } ) ) ,
1622+ initialPageParam : 0 ,
1623+ pages : 2 ,
1624+ getNextPageParam : ( lastPage : { items : Array < string > ; next : number } ) =>
1625+ lastPage . next ,
1626+ } ) ,
1627+ )
1628+
1629+ expect ( result . pages ) . toHaveLength ( 2 )
1630+ expect ( result . pageParams ) . toHaveLength ( 2 )
1631+ expect ( result . pages [ 0 ] ) . toHaveProperty ( 'items' )
1632+ expect ( result . pages [ 1 ] ) . toHaveProperty ( 'items' )
1633+ } )
1634+
13891635 // Companion to the test above: when the query already exists in the cache
13901636 // (e.g. after an initial render or a first hydration pass), the same
13911637 // synchronous thenable resolution must also produce status: 'success'.
0 commit comments