How to Build Infinite Scroll in an Interview
Infinite scroll with IntersectionObserver. Here is how to build it efficiently.
How to Build Infinite Scroll in an Interview
Infinite scroll tests IntersectionObserver and lazy loading. Here is how to build it.
Requirements
- A list that loads more items as the user scrolls.
- Loading indicator while fetching.
- Stop when there is no more data.
- Efficient (no scroll event listeners).
Plan (5 minutes)
- HTML: a list container + a sentinel element at the bottom.
- State: current page, loading, hasMore.
- Logic: IntersectionObserver on the sentinel.
- API: simulate fetching data (or use a real API).
Build Core (40 minutes)
HTML
<div class="list" id="list"></div> <div class="sentinel" id="sentinel">Loading...</div>
JavaScript
let page = 1; let loading = false; let hasMore = true; const list = document.getElementById("list"); const sentinel = document.getElementById("sentinel"); async function fetchItems(pageNum) { // simulate API call return new Promise((resolve) => { setTimeout(() => { if (pageNum > 5) return resolve([]); // no more data after 5 pages const items = Array.from({ length: 10 }, (_, i) => `Item ${(pageNum - 1) * 10 + i + 1}`); resolve(items); }, 500); }); } async function loadMore() { if (loading || !hasMore) return; loading = true; sentinel.textContent = "Loading..."; const items = await fetchItems(page); if (items.length === 0) { hasMore = false; sentinel.textContent = "No more items"; return; } items.forEach((item) => { const div = document.createElement("div"); div.className = "item"; div.textContent = item; list.appendChild(div); }); page++; loading = false; sentinel.textContent = "Load more"; } const observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) loadMore(); }, { rootMargin: "100px" }); observer.observe(sentinel); loadMore(); // initial load
CSS
.list { max-width: 500px; margin: 0 auto; } .item { padding: 16px; border: 1px solid #ddd; margin: 4px 0; border-radius: 4px; } .sentinel { text-align: center; padding: 20px; color: #666; }
Edge Cases (20 minutes)
- Prevent duplicate loading (loading flag).
- Stop when no more data (hasMore flag).
- rootMargin for pre-loading (load before the sentinel is visible).
- Error handling (retry on fetch failure).
- Cleanup (disconnect the observer when done).
The Takeaway
Build infinite scroll: HTML (list + sentinel), JavaScript (IntersectionObserver on the sentinel, fetch on intersect, loading/hasMore flags, append items), CSS (simple list styling). Use rootMargin for pre-loading. Handle edge cases (duplicate loading, no more data, errors, cleanup). This tests IntersectionObserver and lazy loading.
Use IntersectionObserver on a sentinel element at the bottom of the list. When the sentinel is visible, fetch more data and append. Use loading and hasMore flags to prevent duplicate loads and stop when done. Use rootMargin for pre-loading.
IntersectionObserver is more efficient. Scroll events fire on every pixel of scroll, causing performance issues. IntersectionObserver only fires when the target enters or leaves the viewport, with no manual calculations needed.
Use a loading flag: if (loading || !hasMore) return. Set loading to true before fetching, and false after. This prevents multiple simultaneous fetches when the sentinel is visible.
Use a hasMore flag. When the API returns an empty array, set hasMore to false. The loadMore function checks this flag and returns early. Update the sentinel text to 'No more items'.
rootMargin defines a margin around the root (viewport) for the intersection check. Setting rootMargin: '100px' triggers the callback when the sentinel is 100px below the viewport, pre-loading data before the user reaches the bottom. This makes scrolling smoother.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

