Implementing Infinite Scroll with Next.js and IntersectionObserver
Create a list that fetches and displays more items as the user scrolls, using IntersectionObserver for lazy loading.
import { useState, useEffect, useRef, useCallback } from 'react';
Import required hooks and useRef from React.
const useInfiniteScroll = (fetchMoreFunc) => {
// Ref to track the DOM element
const observerRef = useRef(null);
const observer = new IntersectionObserver((entries) => {
const firstEntry = entries[0];
if (firstEntry.isIntersecting) {
fetchMoreFunc(); // Call the function to fetch more items
}
}, {
threshold: 1.0 // Trigger when 100% of the observed item is in view
});
useEffect(() => {
const currentRef = observerRef.current;
observer.observe(currentRef);
return () => {
observer.unobserve(currentRef);
};
}, []);
return observerRef;
};
Creates a custom hook useInfiniteScroll which takes a fetchMoreFunc function. This hook initializes a IntersectionObserver to monitor the element for visibility. When the element comes fully into view, it calls fetchMoreFunc to load more items.
const InfiniteList = ({ fetchMore }) => {
const [items, setItems] = useState([]);
const loadMoreItems = async () => {
const moreItems = await fetchMore();
setItems(currentItems => [...currentItems, ...moreItems]);
};
const observerRef = useInfiniteScroll(loadMoreItems);
// Initial fetch
useEffect(() => {
loadMoreItems();
}, []);
return (
<div>
{items.map((item, index) => (
<div key={index}>{item}</div>
))}
<div ref={observerRef}>Loading more...</div>
</div>
);
};
Implements the InfiniteList component which uses useInfiniteScroll hook by passing it the loadMoreItems function. This component handles the state of items and initial fetch of data rendering each item within a div. It also includes a Loading more... div that is monitored by the IntersectionObserver for triggering further data loads.
export default InfiniteList;
Exports the InfiniteList component to use in other parts of the application.