Generalise the table into one reusable component. The previous tables hard-coded the columns and the data; here you pass both in as props — a columns config and a data array — so the same <DataTable> works for users, products, or anything else. It folds together the two earlier features: column-driven sorting (Data Table II) and pagination (Data Table), in that order.
type Column = { key: string; header: string; sortable?: boolean };
type Row = { id: number; [key: string]: string | number };
function DataTable(props: {
columns: Column[];
data: Row[];
pageSize: number;
}): JSX.Element;
<DataTable columns={userCols} data={users} pageSize={5} />
<DataTable columns={productCols} data={products} pageSize={10} />
→ same component, different config, no code changes
sort by Age, then page → page 2 holds the next-oldest five,
NOT a re-sort of page 2's rows in isolation (sort the whole set first)
columns; cells read row[col.key]. No field names baked in.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.