Coding exercise: implement infinite scrolling in React.

React practical coding · Freshers and experienced

Model answer

Put a small sentinel element at the end of the list and watch it with IntersectionObserver. When it comes into view, load the next page. Do not use a scroll listener that runs on every pixel.

function Feed() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(1);
  const [done, setDone] = useState(false);
  const [busy, setBusy] = useState(false);
  const end = useRef(null);

  useEffect(() => {
    let cancelled = false;
    setBusy(true);
    fetch('/api/posts?page=' + page + '&limit=20').then((r) => r.json()).then((d) => {
      if (cancelled) return;
      setItems((old) => [...old, ...d.items]);
      if (d.items.length < 20) setDone(true);
      setBusy(false);
    });
    return () => { cancelled = true; };
  }, [page]);

  useEffect(() => {
    if (done || busy || !end.current) return;
    const io = new IntersectionObserver(([e]) => e.isIntersecting && setPage((p) => p + 1), { rootMargin: '200px' });
    io.observe(end.current);
    return () => io.disconnect();
  }, [done, busy]);

  return (<>
    <ul>{items.map((x) => <li key={x.id}>{x.title}</li>)}</ul>
    {!done && <div ref={end}>{busy ? 'Loading…' : ''}</div>}
  </>);
}

Mention the trade-offs: keyboard users cannot reach the footer, so offer a "Load more" button as a fallback, and for very long lists use virtualisation.

Tips

Practise it yourself in the React and Angular code playground.

Learn this topic

React.js Full Course: Beginner to Advanced .

Sign in to add your own answer.

More questions