Question presented to candidate: "We have an articles page that loads 20 items at a time from a paginated API. Instead of a Next button, load the next page automatically when the user scrolls close to the bottom of the list. Show a loading state, stop when there is nothing left, and make sure we never fire the same request twice."
Requirements:
- A 420px scroll container; page 1 loads on mount; each page has 20 items, 95 items in total (simulated API, 400ms per request).
- When the user scrolls within 200px of the bottom, fetch the next page and append it.
- Never start a second request while one is in flight, however many scroll events fire.
- Show "Loading more..." while fetching, a Retry button when a request fails (the simulated API fails page 3 once), and "You have reached the end" after the last page.
- If a page does not fill the container, keep loading, because the user cannot scroll to trigger it.
- Expose the busy state to assistive technology.
What a strong answer should cover:
- The near-bottom check:
scrollHeight - scrollTop - clientHeight < threshold, and why a threshold beats waiting for exactly zero. - A synchronous in-flight guard (a ref or plain variable), not only a
loadingstate that updates on the next render. - Page cursor state (
nextPageornull), append-only updates, and a clean end state. - Error handling with a manual retry, and not retrying automatically on every scroll.
- The auto-fill case for tall screens, and the effect cleanup or unmount guard so a late response does not update an unmounted component (including React StrictMode's double effect).
- Passive listeners, and when IntersectionObserver would be the better tool.
Clarifying questions expected:
- "Does the list scroll inside a container or with the whole page?"
- "Is the API page-number or cursor based, and can items shift between pages?"
- "How long will the list get, and do we need to virtualize later?"
Code / implementation expected: Yes. A list component with the scroll handler, a fetch function guarded against duplicates, loading, error and end states, using a simulated API.