Agent Wranglers

Lists and tables Required

Never render thousands of rows

Keep at most 200 rows in the page at once. Page long lists on the server, or render only the visible rows with a virtual list.

How to do it

Ask the API for pages with a cursor, as cursor pagination describes, with a page size such as 50. For lists people scroll through quickly, such as a log, use a virtual list from a library such as TanStack Virtual or vue-virtual-scroller. A virtual list breaks find-in-page and printing, so prefer pages when people search with the browser.

Example

import { useVirtualizer } from '@tanstack/react-virtual';

export function LogList({ entries }: { entries: LogEntry[] }) {
  const scroller = useRef<HTMLDivElement>(null);
  const rows = useVirtualizer({ count: entries.length, getScrollElement: () => scroller.current, estimateSize: () => 36, overscan: 10 });
  return (
    <div ref={scroller} className="log-list" tabIndex={0} aria-label="Log entries">
      <ul className="log-list-inner" style={{ height: rows.getTotalSize() }}>
        {rows.getVirtualItems().map(row => (
          <li key={entries[row.index].id} style={{ transform: `translateY(${row.start}px)` }}>{entries[row.index].message}</li>
        ))}
      </ul>
    </div>
  );
}
PAGE_SIZE = 50

@app.get("/api/log-entries")
def log_entries():
    after = decode_cursor(request.args.get("cursor"))
    rows = log_store.after(current_user().account_id, after, limit=PAGE_SIZE + 1)
    has_more = len(rows) > PAGE_SIZE
    return {
        "items": [row.to_json() for row in rows[:PAGE_SIZE]],
        "nextCursor": encode_cursor(rows[PAGE_SIZE - 1]) if has_more else None,
    }

How to check

Load a list with 10,000 records in a browser test. The page holds no more than 200 row elements at the start and after scrolling to the end.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/lists-and-tables/bounded-lists.