|
import React, { useState, useMemo, useRef, useEffect } from 'react'; |
|
import { FixedSizeList as List } from 'react-window'; |
|
|
|
interface VirtualGameListProps { |
|
games: any[]; |
|
itemHeight: number; |
|
height: number; |
|
width: number; |
|
renderItem: (props: { index: number; style: any; data: any[] }) => React.ReactElement; |
|
} |
|
|
|
export const VirtualGameList: React.FC<VirtualGameListProps> = ({ |
|
games, |
|
itemHeight, |
|
height, |
|
width, |
|
renderItem |
|
}) => { |
|
const listRef = useRef<List>(null); |
|
|
|
return ( |
|
<List |
|
ref={listRef} |
|
height={height} |
|
width={width} |
|
itemCount={games.length} |
|
itemSize={itemHeight} |
|
itemData={games} |
|
overscanCount={5} // Renderizar 5 itens extras para smoother scrolling |
|
> |
|
{renderItem} |
|
</List> |
|
); |
|
}; |
|
|
|
|
|
export const useInView = (ref: React.RefObject<HTMLElement>, threshold = 0.1) => { |
|
const [isInView, setIsInView] = useState(false); |
|
|
|
useEffect(() => { |
|
const element = ref.current; |
|
if (!element) return; |
|
|
|
const observer = new IntersectionObserver( |
|
([entry]) => { |
|
setIsInView(entry.isIntersecting); |
|
}, |
|
{ threshold } |
|
); |
|
|
|
observer.observe(element); |
|
return () => observer.disconnect(); |
|
}, [ref, threshold]); |
|
|
|
return isInView; |
|
}; |
|
|