32 - Infinite Scroll for Loading More Content

Description

Develop a React component that dynamically loads additional content as users scroll down, simulating infinite scrolling.

  • Displays a list of initial content items.

  • Triggers additional content fetching when approaching the bottom of the list.

  • Renders newly loaded content seamlessly below existing items.

  • Provides feedback during loading (e.g., spinner).

  • Supports different data fetching APIs or libraries.

Algorithm

  1. Component Structure:

    • Define a functional component named InfiniteScroll.

    • Accept props for:

      • items: Initial list of data items.

      • fetchMoreItems: Function for fetching additional data.

      • renderItem: Function for rendering individual content items.

      • threshold: Scroll position trigger for fetching more data (optional).

    • Maintain internal state for:

      • page: Current page number for data requests.

      • loading: Boolean flag indicating ongoing data fetching.

  2. Data Fetching and Rendering:

    • Use the useEffect hook to call fetchMoreItems with the current page when it changes.

    • Update the items state with the received data after successful fetching.

    • Render the initial list of items followed by a loading indicator when appropriate.

    • Use the renderItem prop to render individual items within the list.

  3. Scroll Monitoring and Triggering:

    • Attach an event listener to the scroll container (e.g., window or parent element).

    • Calculate the remaining scroll distance from the bottom.

    • Trigger fetchMoreItems when the remaining distance is less than the threshold (if provided).

Code

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

const InfiniteScroll = ({ items, fetchMoreItems, renderItem, threshold = 100 }) => {
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchMoreItems(page).then((data) => {
      setPage((prevPage) => prevPage + 1);
      setItems([...items, ...data]);
      setLoading(false);
    });
  }, [page]);

  const handleScroll = () => {
    const { scrollHeight, clientHeight, scrollTop } = document.documentElement;
    if (scrollTop + clientHeight >= scrollHeight - threshold && !loading) {
      setLoading(true);
    }
  };

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

  return (
    <div className="infinite-scroll-container">
      {items.map((item) => renderItem(item))}
      {loading && <div className="loading-indicator" />}
    </div>
  );
};

export default InfiniteScroll;

Explanation

  1. State Management:

    • page: Tracks the current page for data fetching.

    • loading: Indicates ongoing data fetching.

  2. Data Fetching and Rendering:

    • useEffect calls fetchMoreItems with the current page on each page change.

    • Updates items state with new data and loading to false after successful fetch.

    • Renders items using renderItem prop and a loading indicator if necessary.

  3. Scroll Monitoring and Triggering:

    • handleScroll calculates remaining scroll distance and sets loading to true when nearing the bottom and not already loading.

    • useEffect attaches and removes the scroll event listener.

  4. Performance Optimization:

    • Debouncing the scroll event handler can be implemented to avoid excessive fetches.

    • memoization can be used for better item rendering performance.

Additional Notes

  • This code provides a basic example and can be customized further, like adding a "No more items" message after reaching the data limit.

  • Consider integrating with state management libraries or data fetching libraries for more complex scenarios.

  • Remember to style the scroll container, items, and loading indicator for your desired appearance.

Last updated