DEV Community

Anxiny
Anxiny

Posted on

Infinite Scroll with React Hook & Intersection Observer

In this post, we going to use the useIntersectionObserver hook that I create in

In short, this hook will check if the target element is in the viewport of a document or window.

Ok, let's start with a component that will load a picture:

function Component({ id }: { id: number }) {
  const [data, setData] = useState<any>({});
  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/photos/${id}`)
      .then((res) => res.json())
      .then((data) => {
        setData(data);
      });
  }, []);
  return (
    <div style={{ height: "600px" }}>
      <img src={data.url} alt="pic" />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

then, we can use it inside the App.js:

const pageSize=5;
export default function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      {(() => {
        const children = [];
        for (let i = 1; i <= count * pageSize; i++) {
          children.push(<Component key={i} id={i} />);
        }
        return children;
      })()}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now, we add the hook, a component that can be used as trigger, and an useEffect that can increase the counter:

const pageSize = 5;
export default function App() {
  const [count, setCount] = useState(0);
  const ref = useRef(null);

  const isBottomVisible = useIntersectionObserver(
    ref,
    {
      threshold: 0 //trigger event as soon as the element is in the viewport.
    },
    false // don't remove the observer after intersected.
  );

  useEffect(() => {
    //load next page when bottom is visible
    isBottomVisible && setCount(count + 1);
  }, [isBottomVisible]);

  return (
    <div className="App">
      {(() => {
        const children = [];
        for (let i = 1; i <= count * pageSize; i++) {
          children.push(<Component key={i} id={i} />);
        }
        return children;
      })()}
      <div ref={ref} style={{ width: "100%", height: "20px" }}>
        Bottom
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now we can test the code, here is a demo:

Thank you all!

Top comments (2)

Collapse
 
sonangrai profile image
Sonahang Rai • Edited

Nice
Exactly what I was looking for

Collapse
 
hayoung0lee profile image
Hayoung Lee(이하영)

Thanks!!!! This is the easiest answer I was looking for!!!