Skip to content

Instantly share code, notes, and snippets.

@owaisahmed5300
Last active April 16, 2025 10:39
Show Gist options
  • Save owaisahmed5300/454652bb02059a1e1b55d5ad398501c2 to your computer and use it in GitHub Desktop.
Save owaisahmed5300/454652bb02059a1e1b55d5ad398501c2 to your computer and use it in GitHub Desktop.
React Infinite Scroll Typescript Intersection Observer
import {FC, ReactNode, useCallback, useEffect, useRef} from "react";
interface InfiniteScrollProps {
load: () => void;
hasMore: boolean;
loader: ReactNode;
children?: ReactNode;
endMessage?: ReactNode;
}
export const InfiniteScroll: FC<InfiniteScrollProps> = ({
load,
hasMore,
loader,
children,
endMessage,
}) => {
const sentinelRef = useRef<HTMLDivElement>(null);
const observerRef = useRef<IntersectionObserver | null>(null);
const handleIntersect = useCallback(
(
entries: IntersectionObserverEntry[],
) => {
// Check if the sentinel element is intersecting, and if so, call the load function
if (entries[0].isIntersecting && hasMore) {
load();
}
},
[load, hasMore]
);
useEffect(() => {
// Create a new IntersectionObserver when the component mounts
observerRef.current = new IntersectionObserver(handleIntersect, {
root: null,
rootMargin: "0px",
threshold: 1.0,
});
// Attach the observer to the sentinel element
if (sentinelRef.current) {
observerRef.current.observe(sentinelRef.current);
}
// Clean up the observer when the component unmounts
return () => {
if (observerRef.current) {
observerRef.current.disconnect();
}
};
}, [load, handleIntersect]);
useEffect(() => {
// When the hasMore prop changes, disconnect the previous observer and reattach it to the new sentinel element
if (observerRef.current && sentinelRef.current) {
observerRef.current.disconnect();
observerRef.current.observe(sentinelRef.current);
}
}, [hasMore]);
return (
<div>
{children}
<div ref={sentinelRef}>{hasMore && loader}</div>
{!hasMore && endMessage}
</div>
);
};
export default InfiniteScroll;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment