Skip to content
Live coding · 40 minutes

Infinite list with IntersectionObserver

Build a list in React that loads more items as the user scrolls, in 40 minutes. Use a public test API with pages, or a fake function that returns 20 items after a delay and ends after 5 pages. Use IntersectionObserver on an element at the end of the list, not a scroll event listener. Show loading, error and end-of-list states. Explain your decisions while you code, as in a live round.

Requirements

  • The first page loads on mount; the next page loads when a sentinel element at the end of the list becomes visible
  • Only one request runs at a time, and no page is added to the list twice
  • A loading indicator shows at the end of the list while a page loads
  • After the last page, loading stops and an end message is shown
  • A failed request shows an error with a Retry button and keeps the loaded items
  • The observer is disconnected when the component unmounts
  • Items have stable keys from their ids

What reviewers look for

  • IntersectionObserver is created in an effect with cleanup, with a rootMargin so loading starts before the user reaches the end
  • No duplicate or parallel requests: a guard for loading and for hasMore
  • No stale closure: the observer callback sees the current page and loading state
  • Correct under Strict Mode, where effects run twice in development
  • All states are handled: first load, next page, error with retry, end of list
  • You can say why IntersectionObserver is better here than a scroll listener

Check before you hand it in

  • Scrolling to the end loads the next page, again and again, until the last page
  • No item appears twice, also when I scroll fast, and the network panel shows no two finished requests for the same page
  • After the last page no more requests are sent, and an end message is shown
  • I forced a failed request: an error and a Retry button appeared, the loaded items stayed, and Retry loaded the same page
  • The effect cleanup disconnects the observer
  • I explained each decision aloud, including why I use IntersectionObserver and not a scroll event
  • Loading more on scroll, with the loading and end states, worked within 40 minutes

If there is time

  • Add a Load more button as a fallback and for keyboard users
  • Virtualize the list, so only the visible items are in the DOM
  • Move the logic into a hook, for example useInfiniteList
  • Restore the scroll position after a visit to a detail page