Skip to the solution
MediumMachine Coding12 min read

Build a Pagination component

226 views

The problem

Question presented to candidate: "Build a reusable pagination control. The parent tells it the current page and the total number of pages, and it tells the parent when the user picks a page. Show the first and last page, a few pages around the current one, ellipses for the rest, and Prev and Next buttons that are disabled at the ends. It should not jump around in width as I click through."

Requirements:

  • A controlled component: page and totalPages come in, a page-change event or callback goes out; it keeps no page state of its own.
  • A page-window function: always show page 1, the last page, the current page and one sibling on each side; replace hidden runs with ….
  • Constant width: once there are more than 7 pages the control always renders exactly 7 items, so buttons do not shift under the pointer.
  • Never hide a single page behind … (an ellipsis that stands for one page is worse than the page itself).
  • Prev and Next disabled on the first and last page; clicking the current page does nothing; nothing renders for a single page.
  • A small demo: 194 results with a per-page selector that keeps the first visible result on screen when the page size changes.

What a strong answer should cover:

  • The window algorithm written as a pure function that is easy to unit test, separate from rendering.
  • Edge pages: 1, 2, 3, 4 and their mirrors at the end, totals of 1, 7 and 8, and the symmetry between both ends.
  • Why ellipsis items need stable, distinct keys (gap-left and gap-right), not the index.
  • The controlled API (value in, event out) and where the page state lives.
  • Accessibility: a nav landmark with a label, aria-current="page", labelled Prev and Next, real buttons and a visible focus ring.

Clarifying questions expected:

  • "How many siblings around the current page, and should that be configurable?"
  • "Do we know the total, or is this a cursor-based API with only next and previous?"
  • "Should First and Last be separate buttons, or is showing page 1 and the last page enough?"

Code / implementation expected: Yes. A pure pageItems(current, total, siblings) function plus a controlled component in React, Vue or Angular, with the edge cases demonstrated.

  • React
  • Pagination
  • Data

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read · 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useState } from "react";
import Pagination from "./src/components/Pagination";

const ITEMS = Array.from({ length: 194 }, (_, i) => "Result " + (i + 1));
const SIZES = [10, 25, 50];

export default function App() {
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const totalPages = Math.ceil(ITEMS.length / pageSize);
  const start = (page - 1) * pageSize;
  const visible = ITEMS.slice(start, start + pageSize);

  // Keep the first visible row on screen when the page size changes.
  function changeSize(event) {
    const size = Number(event.target.value);
    setPageSize(size);
    setPage(Math.floor(start / size) + 1);
  }

  return (
    <main className="demo">
      <h1>Search results</h1>
      <div className="toolbar">
        <p data-testid="range" aria-live="polite">
          Showing {start + 1}–{start + visible.length} of {ITEMS.length}
        </p>
        <label>
          Per page{" "}
          <select data-testid="size" value={pageSize} onChange={changeSize}>
            {SIZES.map((s) => (
              <option key={s} value={s}>
                {s}
              </option>
            ))}
          </select>
        </label>
      </div>
      <ol className="results" start={start + 1}>
        {visible.slice(0, 3).map((r) => (
          <li key={r}>{r}</li>
        ))}
        {visible.length > 3 && (
          <li className="more">… {visible.length - 3} more on this page</li>
        )}
      </ol>
      <Pagination page={page} totalPages={totalPages} onPageChange={setPage} />
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 68 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

Build a Quiz App

Continue