System Designmedium
Implement infinite scroll with IntersectionObserver
Implement an infinite-scrolling list that fetches the next page of data when the user reaches the bottom of the list, using IntersectionObserver instead of scroll events.
Asked at Amazon, Netflix, Meta
Answer
class InfiniteScroll { constructor(container, fetchPage) { this.container = container this.fetchPage = fetchPage this.page = 1 this.loading = false this.done = false // Sentinel element sits at the bottom of the list this.sentinel = document.createElement('div') container.appendChild(this.sentinel) this.observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) this._load() }, { rootMargin: '200px 0px' } // pre-fetch 200px before visible ) this.observer.observe(this.sentinel) } async _load() { if (this.loading || this.done) return this.loading = true this._showSpinner() const items = await this.fetchPage(this.page) if (!items.length) { this.done = true this.observer.disconnect() } else { items.forEach(item => { const el = document.createElement('div') el.className = 'item' el.textContent = item.title this.container.insertBefore(el, this.sentinel) }) this.page++ } this._hideSpinner() this.loading = false } _showSpinner() { this.sentinel.textContent = 'Loading…' } _hideSpinner() { this.sentinel.textContent = '' } } // Usage const container = document.querySelector('#feed') const fetchPage = async (page) => { const r = await fetch('/api/feed?page=' + page) return r.json() } const infiniteList = new InfiniteScroll(container, fetchPage) void infiniteList