gridcn1.2.2

SWR

Server-mode pagination with useSWR, where the page is the cache key and a scoped revalidate covers edits.

Same server mode through useSWR: the key ["rows", page, pageSize] makes paging back instant (the page is cached by key), and the scoped mutate returned by the hook revalidates the current page after an edit.

Loading page…
Name
Email
Role
Score
No rows
1–25 of 1000
pnpm dlx shadcn@latest add @gridcn/data-grid-pagination-swr-demo

The wiring

const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(25);

const { data, isLoading, mutate } = useSWR(
  ["rows", page, pageSize] as [string, number, number],
  (key) => api.fetchPage({ page: key[1], pageSize: key[2] }),
);

const pager = useDataGridPagination({
  page,
  pageSize,
  total: data?.total ?? initialTotal,
  onPageChange: setPage,
  onPageSizeChange: (next) => {
    setPageSize(next);
    setPage(1);
  },
});

The fetcher receives the key itself as its argument (the SWR 2.x convention), hence the tuple cast. SWR has no built-in keep-previous, so the demo keeps the last fetched rows in local state and only swaps them when new data lands. The grid keeps showing the old page while the next one is in flight.

The edit story

const onDataChange = useCallback(
  (_next: readonly Row[], change: DataChange<Row>) => {
    api.save(change.ops);
    void mutate(undefined, { revalidate: true }); // scoped to this hook's key
  },
  [mutate],
);

The scoped mutate only touches the current page's key. If the same page is shown by more than one useSWR consumer (a summary panel, for instance), revalidate the key globally instead: mutate(["rows", page, pageSize], undefined, { revalidate: true }).

Behavior reference

On this page