#Infinite Scroll - React
5 messages · Page 1 of 1 (latest)
part1
type WSMessage =
| { type: "initialHistoryItems"; items: IHistoryRoomItem[] }
const History = () => {
const [historyItems, setHistoryItems] = useState<IHistoryRoomItem[]>([]);
const [page, setPage] = useState<number>(1);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [endOfData, setEndOfData] = useState<boolean>(false);
const [scrollTop, setScrollTop] = useState<number>(0);
const { user, setUser, ws } = useUserContext();
const bodyRef = useRef<HTMLDivElement>(null);
const fetchData = useCallback(() => {
if (endOfData || isLoading) return;
setIsLoading(true);
ws.sendJsonMessage({
type: "getHistoryItems",
page: page,
});
setPage(page + 1);
}, [page, isLoading]);
part2
function handleScroll() {
if (!bodyRef.current) return;
setScrollTop(bodyRef.current.scrollTop);
}
useEffect(() => {
if (!bodyRef.current) return;
if (
bodyRef.current.scrollTop +
bodyRef.current.clientHeight +
bodyRef.current.clientHeight / 2 <=
bodyRef.current.scrollHeight ||
isLoading
) {
return;
}
fetchData();
}, [scrollTop]);
useEffect(() => {
if (
bodyRef.current &&
bodyRef.current.clientHeight >= bodyRef.current.scrollHeight
) {
fetchData();
}
}, [historyItems]);
function handleWSMessage(msg: WSMessage) {
if (msg.type === "initialHistoryItems") {
setIsLoading(false);
if (msg.items.length === 0) {
setEndOfData(true);
return;
}
// Check for same page
if (historyItems.length !== 0 && historyItems[0]._id === msg.items[0]._id)
return;
setHistoryItems((prevState) => {
return [
...prevState,
...msg.items,
];
});
}
}
useEffect(() => {
handleWSMessage(ws.lastJsonMessage);
}, [ws.lastJsonMessage]);
return (
<div
className="flex flex-grow flex-col overflow-auto"
ref={bodyRef}
onScroll={handleScroll}
>
{historyItems.map((e) => (
<HistoryRoomItem {...e} key={e._id} />
))}
</div>
);
};
@ me for anything so i can respond instantly
help