Pablo Jurado

05 July, 2022

Infinite scroll with React

How to create an infinite scroll component with React Hooks

First, we need a custom hook that will return true every time the user scrolls to the bottom of the component. For this, we use the intersection observer API

function useOnScreen(ref: React.RefObject<HTMLElement>) {
  const [isIntersecting, setIntersecting] = React.useState(false);

  const observer = new IntersectionObserver(([entry]) =>
    setIntersecting(entry.isIntersecting)
  );

  useEffect(() => {
    if (ref.current) {
      observer.observe(ref.current);
    }
    return () => observer.disconnect();
  }, []);

  return isIntersecting;
}

export default useOnScreen;

Now, we can utilize that custom hook on our Infinite Scroll component. The component is a wrapper that adds a div element to the bottom. We pass the div reference to our useOnScreen hook, so we will know every time this element is visible.

interface Props {
  children: React.ReactNode;
  callback: (nexPage: number) => void;
  currentPage: number;
}

function InfiniteScroll({ children, callback, currentPage }: Props) {
  const ref = React.useRef<HTMLDivElement>(null);
  const isVisible = useOnScreen(ref);


  useEffect(() => {
    if (isVisible) callback(page + 1);
  });

  return (
    <div>
      {children}
      <div ref={ref}></div>
    </div>
  );
}

And we will use the component like so:

<InfiniteScroll
  callback={(pageNumber) => getNextPage(pageNumber)}
  page={currentPage}
>
  <ul>
    {allPages.map((item) => <li key={item.id}>{item.name}</li>)}
  </ul>
</InfiniteScroll>