I am trying to render a huge list of data in React. I know I can use react-window for this usecase but wanted to try if we can implement a similar window based rendering using Intersection Observer API.
I have written this component to try the same. But Here my component is rendering the whole 10,000 divs even if it is not in view port as i am iterating over the data. Is there any way to prevent rendering if the element is not there in viewport similar to react-window. Thank you in advance.
import React from 'react';
import './CustomVirtualizedList.css';
import faker from 'faker';
const generateFakeData = (() => {
const data = [];
for (let i = 0; i < 10000; i++) {
data.push({ id: i, selected: false, label: faker.address.state() })
}
return () => data;
})();
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
const ListElement = (props) => {
const [visible, setVisible] = React.useState(false);
const {containerRef} = props;
const elementRef = React.useRef();
let intersectionObserver;
const onVisibilityChange = ([entry]) => {
setVisible(entry.isIntersecting)
}
React.useEffect(() => {
console.log(props);
intersectionObserver = new IntersectionObserver(onVisibilityChange, containerRef.current);
intersectionObserver.observe(elementRef.current);
return () => {
intersectionObserver.disconnect()
}
}, [])
return <div
ref={elementRef}
style={{ backgroundColor: getRandomColor() }}
className="listElement">
{visible ? 'I am visible' : 'I am not visible'}
</div>
}
export const ListContainer = () => {
const containerRef = React.useRef();
const [data, setData] = React.useState(generateFakeData())
return (
<div className="listContainer">
{data.map(val => {
return <ListElement containerRef={containerRef} {...val} />
})}
</div>
);
};