import React, { memo, useState, useEffect } from 'react'; import handleViewport from 'react-in-viewport'; import { chunk } from 'lodash'; import ErrorBoundary from './ErrorBoundary'; const SmartListBatch = handleViewport( ({ items, inViewport, forwardedRef, setItemHeight, itemHeight, itemComponent: ItemComponent, itemProps, batchIndex, chunkSize, className = '', isFirst, isLast, }) => { // Listen for changes to our height, and pass it up to our Grid. This is then used to build the // placeholder elements when out of viewport. We only care about the first item because this // represents the same heights for everything else (in almost all circumstances). const { current: { clientHeight } = {} } = forwardedRef; useEffect(() => { if (isFirst && clientHeight !== itemHeight) { setItemHeight(clientHeight); } }, [clientHeight]); const itemIndex = (bi = 0, ii = 0) => { if (bi === 0) return ii; return ii + (chunkSize * bi); } return (
{inViewport || isFirst || isLast ? (
{ items.map((item, index) => ( itemIndex(batchIndex, index)} {...itemProps} /> )) }
) : (
)}
); }, ); const SmartList = memo(({ items, itemComponent, chunkSize = 20, initialHeight = '50vh', itemProps, className, }) => { if (!items || !items.length) return null; if (!itemComponent) return null; const [itemHeight, setItemHeight] = useState(initialHeight); const chunks = chunk(items, chunkSize); return ( { chunks.map((chunked, index) => ( )) } ); }); export default { SmartList, }; export { SmartList, };