Blog>
Snippets

Optimizing Infinite Scroll Performance with Debouncing Scroll Events

Explain how to implement debouncing for scroll events in a React infinite scroll implementation to optimize performance and reduce the number of data fetching operations.
const [isLoading, setIsLoading] = useState(false);
const [items, setItems] = useState([]);
Initializing state for loading indication and storing items fetched from the server.
const handleScroll = debounce(() => {
  if (window.innerHeight + document.documentElement.scrollTop !== document.documentElement.offsetHeight || isLoading) return;
  setIsLoading(true);
  fetchMoreData();
}, 100);
Debouncing scroll event handler to limit the frequency of fetch calls. It only triggers data fetching when the user has scrolled to the bottom of the page and is not currently loading data.
useEffect(() => {
  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, [isLoading]);
Effect hook to manage adding and removing the scroll event listener. It cleans up the event listener on component unmount to prevent memory leaks.
const fetchMoreData = async () => {
  const newData = await fetchData();
  setItems(prevItems => [...prevItems, ...newData]);
  setIsLoading(false);
};
Function to fetch more data from the server. It appends the new data to the existing items and resets the loading state.
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}
Utility function to debounce another function. It delays the execution of the function until after `wait` milliseconds have elapsed since the last time it was invoked.