Coding exercise: implement infinite scrolling in React.
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
- rootMargin starts loading a little before the user reaches the end.
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
- Coding exercise: build a Todo application in React.
- Coding exercise: create a search box with debounce in React.
- Coding exercise: fetch API data and display it in a table in React.
- Coding exercise: implement pagination in React.
- Coding exercise: create a login form with validation in React.
- Coding exercise: build a parent-child communication example in React.