-
-
Notifications
You must be signed in to change notification settings - Fork 390
Description
Assume I have the following settings:
The container height: 400
The row height: 40
const virtual = useVirtual({
size: 1000,
parentRef,
overscan: 20,
estimateSize: useCallback(() => 40, [size]),
})
It seems that the container re-renders every visible row every time new row appears. This behavior maybe intentional but what if my row is heavyweight and the cost to re-render them is not trivial?
What I want to do is re-render only when the last row is visible.
In the above setup, I should see re-render happen once when i scroll to the 30th element, and insert next 20 element since overscan is 20.
Edit:
After play around with the source code, I see that setRange(prevRange => calculateRange(latestRef.current, prevRange)) actually cause the re-render every time index change.
I changed the if condition from
if (!prevRange || prevRange.start !== start || prevRange.end !== end) {
return {
start: start,
end: end
};
}
to
if (!prevRange ||
Math.abs(start - prevRange.start) > overscan - 1 ||
Math.abs(end - prevRange.end) > overscan - 1
) {
return {
start: start,
end: end
};
}
It reduce re-render from 999 to 50 when the data size is 1000 and overscan is 20.
Maybe we can allow developer to pass custom calculateRange function if they need to optimize performance? or improve calculateRange when overscan is used?
https://github.com/tannerlinsley/react-virtual/blob/master/src/index.js#L77