How to Implement Infinite Scroll with Observer in React
Infinite scrolling is a popular technique used in web applications to load and display content dynamically as the user scrolls down the page. Instead of loading all the content at once, infinite scroll fetches and appends new data when the user reaches the end of the current content.
What is Intersection Observer?
The Intersection Observer API is a powerful browser API that allows us to efficiently detect when an element enters or exits the viewport. It provides a way to observe changes in the intersection of a target element with its container or the viewport. By utilizing the Intersection Observer, we can trigger actions when elements become visible or hidden on the screen.
Setting Up the Intersection Observer Hook
First, let’s create a custom hook called useIntersect that encapsulates the functionality of the Intersection Observer. Here’s the code for the useIntersect hook:
import { useCallback, useState } from "react";
type UseIntersect<Node> = {
readonly ref: (node: Node) => void;
readonly observer: IntersectionObserver | undefined;
readonly entry: IntersectionObserverEntry | undefined;
};
export function useIntersect({
threshold = 1.0,
rootMargin = "0px",
root = null,
}: Partial<IntersectionObserverInit>): UseIntersect<null> {
const [observer, setObserver] = useState<IntersectionObserver>();
const [entry, setEntry] = useState<IntersectionObserverEntry>();
const ref = useCallback(
node => {
if (node) {
const _observer = new IntersectionObserver(
([_entry]) => {
setEntry(_entry);
},
{ root, rootMargin, threshold }
);
_observer.observe(node);
setObserver(observer);
}
},
[root, rootMargin, threshold]
);
return { ref, entry, observer };
}
The useIntersect hook takes an optional configuration object for the Intersection Observer’s options such as threshold, rootMargin, and root. It returns an object containing a ref function to attach to the element we want to observe, the observer instance, and the entry representing the intersection observer’s entry for the observed element.
Implementing Infinite Scroll
To implement infinite scroll, we need to create a component that uses the useIntersect hook and listens for the intersection event.
import { useEffect } from "react";
import { useIntersect } from "./useIntersect";
export function ScrollIntersector(props: {
onIntersect: () => void,
}): JSX.Element {
const { entry, observer, ref } = useIntersect({ threshold: 1.0 });
useEffect(() => {
if (entry?.isIntersecting) {
props.onIntersect();
observer?.disconnect();
}
}, [entry?.isIntersecting, observer]);
return <div ref={ref} />;
}
In the ScrollIntersector component, we use the useIntersect hook to obtain the entry, observer, and ref. We listen for changes in the entry.isIntersecting property, which indicates whether the observed element is currently intersecting the viewport. When the element becomes visible, we call the onIntersect function provided by the parent component, typically used to load additional data. We also disconnect the observer to prevent unnecessary observations after the intersection occurs.
Integrating Infinite Scroll in a React Component
To integrate the infinite scroll functionality into a React component, we can use the ScrollIntersector component alongside the existing content.
return (
<Box>
<Table
onHeaderClick={onHeaderClick}
columns={columns}
rows={rows}
fixedHeader={{ top: TOP_POSITION }}
>
<ScrollIntersector onIntersect={onBottomReached} />
</Table>
</Box>
);
In this example, the ScrollIntersector component is placed inside a Table component. When the bottom of the table is reached, the onBottomReached function will be called, typically used to load more rows or content.
Conclusion
Implementing infinite scroll with the Intersection Observer API in React allows us to create dynamic and performant applications that load content as the user scrolls. By leveraging the useIntersect hook and the ScrollIntersector component, we can easily observe elements and trigger actions when they become visible on the screen. Remember to adjust the configuration options of the Intersection Observer based on your specific requirements.
Happy scrolling!