import { useWatch } from '@/hooks/useWatch'; import { VirtualItem, useVirtualizer } from '@tanstack/react-virtual'; import { Empty } from 'antd'; import { last } from 'lodash-es'; import React, { useRef } from 'react'; interface VirtualListProps { allData: T[]; hasNextPage: boolean | undefined; isFetchingNextPage: boolean; onFetchNextPage: () => void; estimateSize: (index: number) => number; renderItem: (item: VirtualItem) => React.ReactElement; } export const SimpleVirtualList: React.FC = React.memo( (props) => { const { allData, hasNextPage, isFetchingNextPage, onFetchNextPage, estimateSize, renderItem, } = props; const parentRef = useRef(null); const rowVirtualizer = useVirtualizer({ count: hasNextPage ? allData.length + 1 : allData.length, getScrollElement: () => parentRef.current, estimateSize, overscan: 5, }); const virtualItems = rowVirtualizer.getVirtualItems(); useWatch([virtualItems], () => { const lastItem = last(virtualItems); if (!lastItem) { return; } if ( lastItem.index >= allData.length - 1 && hasNextPage && !isFetchingNextPage ) { onFetchNextPage(); } }); return (
{virtualItems.length === 0 && }
{virtualItems.map((virtualItem) => renderItem(virtualItem))}
); } ); SimpleVirtualList.displayName = 'SimpleVirtualList';