0
0
ReactHow-ToBeginner · 4 min read

How to Create Infinite Scroll in React: Simple Guide

To create infinite scroll in React, use the useEffect hook to add a scroll event listener that checks when the user nears the page bottom, then load more data by updating state. Combine this with useState to store items and a loading flag to prevent multiple fetches.
📐

Syntax

Infinite scroll in React typically uses these parts:

  • useState to hold the list of items and loading status.
  • useEffect to add and clean up the scroll event listener.
  • A scroll handler function that checks if the user scrolled near the bottom.
  • A function to fetch or generate more items and update state.
javascript
import React, { useState, useEffect } from 'react';

function InfiniteScrollComponent() {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    function handleScroll() {
      if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100 && !loading) {
        loadMoreItems();
      }
    }

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [loading]);

  function loadMoreItems() {
    setLoading(true);
    // Fetch or generate more items here
    setTimeout(() => {
      setItems(prev => [...prev, ...Array.from({ length: 10 }, (_, i) => prev.length + i + 1)]);
      setLoading(false);
    }, 1000);
  }

  return null; // UI omitted for brevity
}

export default InfiniteScrollComponent;
💻

Example

This example shows a list that loads 10 more numbers each time you scroll near the bottom. It uses React hooks to manage state and scroll events.

javascript
import React, { useState, useEffect } from 'react';

export default function InfiniteScrollExample() {
  const [items, setItems] = useState(Array.from({ length: 20 }, (_, i) => i + 1));
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    function onScroll() {
      if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 50 && !loading) {
        loadMore();
      }
    }

    window.addEventListener('scroll', onScroll);
    return () => window.removeEventListener('scroll', onScroll);
  }, [loading]);

  function loadMore() {
    setLoading(true);
    setTimeout(() => {
      setItems(prev => [...prev, ...Array.from({ length: 10 }, (_, i) => prev.length + i + 1)]);
      setLoading(false);
    }, 1000);
  }

  return (
    <main style={{ maxWidth: '400px', margin: 'auto', padding: '1rem' }}>
      <h2>Infinite Scroll List</h2>
      <ul>
        {items.map(item => (
          <li key={item} style={{ padding: '0.5rem 0', borderBottom: '1px solid #ccc' }}>
            Item {item}
          </li>
        ))}
      </ul>
      {loading && <p>Loading more items...</p>}
    </main>
  );
}
Output
A scrollable list showing items numbered 1 to 20 initially. When you scroll near the bottom, it loads 10 more items each time, showing a "Loading more items..." message briefly.
⚠️

Common Pitfalls

Common mistakes when creating infinite scroll in React include:

  • Not cleaning up the scroll event listener, causing memory leaks.
  • Triggering multiple loads at once by not checking a loading flag.
  • Using fixed scroll positions without considering dynamic content height.
  • Not throttling or debouncing scroll events, leading to performance issues.

Always remove event listeners in useEffect cleanup and use a loading state to prevent repeated fetches.

javascript
/* Wrong: No cleanup and no loading check */
useEffect(() => {
  window.addEventListener('scroll', () => {
    if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100) {
      loadMoreItems();
    }
  });
}, []);

/* Right: Cleanup and loading check */
useEffect(() => {
  function onScroll() {
    if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100 && !loading) {
      loadMoreItems();
    }
  }
  window.addEventListener('scroll', onScroll);
  return () => window.removeEventListener('scroll', onScroll);
}, [loading]);
📊

Quick Reference

  • useState: Store items and loading state.
  • useEffect: Add and remove scroll listener.
  • Scroll handler: Detect near-bottom scroll.
  • Loading flag: Prevent multiple fetches.
  • Cleanup: Remove event listener on unmount.

Key Takeaways

Use useEffect to add and clean up scroll event listeners properly.
Check scroll position and a loading flag before fetching more data.
Update state with new items to trigger re-render and show more content.
Avoid multiple simultaneous loads by managing a loading state.
Clean up event listeners to prevent memory leaks and bugs.