I'm using react-virtuoso
library to render a simple virtual list. The code is very straightforward. I pass this overscan
props and expect the virtual list to render n
items above and below the viewport but it's not working.
The ExpensiveComponent
s still renders 'loading...' text when I'm scrolling up and down a little. Here is the code:
import { Virtuoso } from "react-virtuoso";
import { useEffect, useState, useRef, PropsWithChildren } from "react";
function ExpensiveComponent({ children }: PropsWithChildren<{}>) {
const [render, setRender] = useState(false);
const mountRef = useRef(false);
useEffect(() => {
mountRef.current = true;
setTimeout(() => {
if (mountRef.current) {
setRender(true);
}
}, 150);
return () => void (mountRef.current = false);
}, []);
return (
<div style={{ height: 150, border: "1px solid pink" }}>
{render ? children : "Loading..."}
</div>
);
}
function App() {
return (
<Virtuoso
style={{ height: "400px" }}
totalCount={200}
overscan={3} // ----------> this line does not work
itemContent={(index) => {
return <ExpensiveComponent>{index}</ExpensiveComponent>;
}}
/>
);
}
I missed this detail from the docs. Unlike react-window API, the overscan
unit is pixel instead of row in virtual list, in my case I need to increase the overscan
to 900px
and it seems to be working now.
<Virtuoso
style={{ height: "400px" }}
totalCount={200}
overscan={900}
itemContent={(index) => {
return <ExpensiveComponent>{index}</ExpensiveComponent>;
}}
/>