I'm currently using React Virtualised to virtualise a list. The caveat of this, is that my list is actually a grid layout, my component return statement looks like the below:
So the list actually ends up rendering a grid format. screenshot below illustrates the output atm anyway.
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
Depending on how much space there is to work with. AutoResizer adjusts how many columns there is within my (dummy) grid and all is well with the world.
const getMaxItemsAmountPerRow = (rowWidth, itemWidth) => {
return Math.max(Math.floor(rowWidth / itemWidth), 1);
};
const generateIndexesForRow = (rowIndex, rowWidth, itemWidth, itemsAmount) => {
const result = [];
const maxItemsPerRow = getMaxItemsAmountPerRow(rowWidth, itemWidth);
const startIndex = rowIndex * maxItemsPerRow;
for (
let i = startIndex;
i < Math.min(startIndex + maxItemsPerRow, itemsAmount);
i += 1
) {
result.push(i);
}
return result;
};
const getRowsAmount = (rowWidth, itemWidth, itemsAmount, hasMore) => {
const maxItemsPerRow = getMaxItemsAmountPerRow(rowWidth, itemWidth);
const returnVal = Math.ceil(itemsAmount / maxItemsPerRow) + (hasMore ? 1 : 0);
return returnVal;
};
return (
<>
<AutoSizer disableHeight>
{({ width: rowWidth }) => {
const rowCount = getRowsAmount(
rowWidth,
itemWidth,
items.length,
hasMore,
);
return (
<InfiniteLoader
ref={infiniteLoaderRef}
rowCount={rowCount}
isRowLoaded={({ index }) => {
const indexes = generateIndexesForRow(
index,
rowWidth,
itemWidth,
items.length,
);
const allItemsLoaded = indexes.length > 0;
return !hasMore || allItemsLoaded;
}}
loadMoreRows={loadMoreRows}
>
{({ onRowsRendered }) => (
<WindowScroller>
{({ registerChild }) => (
<>
<List
height={calcGridHeight()}
width={rowWidth}
rowCount={rowCount}
overscanRowCount={96}
ref={registerChild}
rowHeight={itemHeight}
onRowsRendered={onRowsRendered}
rowRenderer={({
index,
style,
key,
isVisible,
isScrolling,
}) => {
const itemsForRow = generateIndexesForRow(
index,
rowWidth,
itemWidth,
items.length,
).map((itemIndex) => items[itemIndex]);
return (
<ListRow style={style} key={key} ref={gridRowRef}>
{itemsForRow.map((item, itemIndex) => (
<ListItem key={itemIndex}>
{children(
item,
isVisible,
isScrolling,
itemsForRow.length,
)}
</ListItem>
))}
</ListRow>
);
}}
noRowsRenderer={noRowsRenderer}
/>
</>
)}
</WindowScroller>
)}
</InfiniteLoader>
);
}}
</AutoSizer>
</>
);
The render prop of children calls up to another component which does the rendering of my items:
const renderFunc = (item, isVisible, isScrolling) => {
return isVisible ? (
<Item
key={item.id}
item={item}
/>
) : (
<DummyItem />
);
};
However, my isVisible variable which (is generated internally within react-virtualised) gets passed into the function appears to be returning false a little too early.
This results in the following behaviour when scrolling:
In other words, my overscan isn't eager enough even when scrolling slowly. I strongly suspect this is due to my layout.
To cut to the chase, from reading around - (rightly or wrongly) I think the overscan indices getter potentially needs to be adjusted, see here: https://github.com/bvaughn/react-virtualized/blob/master/docs/Grid.md#overscanindicesgetter
however, clueless as I am, I can't make head nor tail of this documentation to understand exactly what its doing, and potentially what I'd need to do to resolve things to make my overscan a bit more eager. You'll notice overscanRowCount={96} has already been added to the List, and I would have thought that high number should have been more than enough additional html for the component to work with even at slow scroll speeds.. hence why I think potentially overscanIndicesGetter is the key to my problem.
Any help appreciated, even if its to help me get my head around the overscanIndicesGetter function and what its doing under the hood. I tried console.logging some of the internal variables but I was still none the wiser as it seems to fluctuate wildly in terms of its output.
from React Virtualised trouble understanding overscanIndicesGetter

No comments:
Post a Comment