ZOBACZ NAJNOWSZE INFORMACJE

Aktualności

Mantine DataTable for React: installation, setup, and interactive examples






Mantine DataTable for React: Installation, Setup & Examples







Mantine DataTable for React: installation, setup, and interactive examples

If you’re building a product UI and you need a React table component that looks sane by default,
plays nicely with theming, and doesn’t turn “show 20 rows of users” into a three-day side quest, you’ll likely end up
at mantine-datatable.
In plain terms: it’s an opinionated, ergonomic way to build a React data table Mantine developers can ship.

This guide is a practical mantine-datatable tutorial: you’ll install it, wire it into Mantine,
build a first table, then level it up into an React interactive table with sorting, pagination,
selection, and server-side data patterns. No mysticism—just the parts you’ll copy into a real codebase.

Quick context for voice search / TL;DR: Mantine DataTable is best when you want an interactive table UI
in React with Mantine styling. If you need Excel-level virtualization for 100k+ rows in the browser, you’re in “React data grid”
territory and should plan for server-side pagination or specialized grid tooling.

Why Mantine DataTable (and when you should consider a data grid instead)

A lot of “React table” conversations start with a library comparison spreadsheet… and end with a team shipping a table that
still can’t handle loading states or row actions without duct tape. The main selling point of
mantine-datatable is that
it gives you a production-friendly table UI that matches Mantine’s design language and common application needs.
That’s why it often shows up for queries like Mantine DataTable React and React table with Mantine.

The “table vs grid” decision is less philosophical than it sounds. If your UI shows tens to hundreds (maybe a few thousand)
of rows with sorting/pagination/selection, a table component is usually the right tool—especially if you’re already on Mantine.
If you must render huge datasets in one scroll without paging, you’re looking at a React data grid use case
where virtualization is a first-class requirement.

The nice part: you don’t have to guess early. You can start with Mantine DataTable, implement server-side pagination/sorting,
and keep performance under control. That covers many “large dataset” products because users rarely need all rows at once;
they need the right rows fast (plus filters, search, and meaningful sorting).

Mantine DataTable installation and setup (React, Vite, Next.js)

For mantine-datatable installation, treat it as two layers: (1) Mantine itself and its provider setup,
then (2) the DataTable package. Most “it renders but looks broken” issues come from missing Mantine styles or skipping
provider wiring.

If you’re new to the ecosystem, Mantine’s own Mantine UI table
is a lower-level primitive. mantine-datatable sits above that layer and focuses on interactive behaviors.
The setup is still straightforward: install dependencies, ensure global styles are loaded, then render a DataTable.

Here’s a safe, repeatable setup checklist (works for Vite and is conceptually the same for Next.js):

  1. Install Mantine core dependencies (if not already present).
  2. Install mantine-datatable.
  3. Wrap your app with MantineProvider and import required styles.
// npm
npm i @mantine/core @mantine/hooks
npm i mantine-datatable

// or pnpm
pnpm add @mantine/core @mantine/hooks mantine-datatable
// main.tsx / main.jsx (Vite example)
import React from "react";
import ReactDOM from "react-dom/client";
import { MantineProvider } from "@mantine/core";

// Depending on your Mantine version, you may also need global styles imports.
// Check Mantine docs for the exact imports for your version.
import "@mantine/core/styles.css";

import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <MantineProvider defaultColorScheme="light">
      <App />
    </MantineProvider>
  </React.StrictMode>
);

If you want a second walkthrough, this external guide is a decent companion:
getting started with Mantine DataTable in React.
Use it for comparison—but keep your source of truth as the package docs/repo and your own app constraints.

Mantine DataTable basic usage: your first table (columns, records, sorting)

The mental model is simple: you provide records (your data array) and columns (how to render fields).
That’s the heart of mantine-datatable basic usage and pretty much every mantine-datatable example
you’ll find in the wild.

Start with a small dataset, then add sorting and pagination once you have a clean render. When you’re aiming for a featured snippet,
the one-sentence explanation is: “A Mantine DataTable renders an array of records using a columns configuration that maps fields to UI.”

Below is a minimal but real-world-ish table with sortable columns and a stable row key. (Yes, stable keys matter. No, React will not
forgive you for using array indices when rows are re-ordered.)

import React, { useMemo, useState } from "react";
import { DataTable, type DataTableSortStatus } from "mantine-datatable";

type User = {
  id: string;
  name: string;
  email: string;
  role: "Admin" | "Editor" | "Viewer";
};

const seedUsers: User[] = [
  { id: "u_1", name: "Ava Stone",  email: "ava@example.com",  role: "Admin" },
  { id: "u_2", name: "Noah Reed",  email: "noah@example.com", role: "Editor" },
  { id: "u_3", name: "Mia Chen",   email: "mia@example.com",  role: "Viewer" },
];

export default function UsersTable() {
  const [sortStatus, setSortStatus] = useState<DataTableSortStatus<User>>({
    columnAccessor: "name",
    direction: "asc",
  });

  const records = useMemo(() => {
    const sorted = [...seedUsers].sort((a, b) => {
      const aValue = a[sortStatus.columnAccessor as keyof User];
      const bValue = b[sortStatus.columnAccessor as keyof User];
      return String(aValue).localeCompare(String(bValue));
    });
    return sortStatus.direction === "desc" ? sorted.reverse() : sorted;
  }, [sortStatus]);

  return (
    <DataTable
      withTableBorder
      withColumnBorders
      highlightOnHover
      records={records}
      idAccessor="id"
      columns={[
        { accessor: "name", sortable: true },
        { accessor: "email" },
        { accessor: "role", sortable: true },
      ]}
      sortStatus={sortStatus}
      onSortStatusChange={setSortStatus}
    />
  );
}

That snippet covers the “local” case. If your dataset is tiny, client-side sorting is fine. If it’s not tiny,
do not “just fetch everything” and hope it’s okay—your future self will remember your name, and not in a good way.

From table to React interactive table: selection, actions, and server-side data

“Interactive” usually means three things: (1) select rows, (2) perform actions (edit/delete/view), and (3) load data from an API
with pagination and sorting. This is where Mantine DataTable shines as a React data table library for product UIs,
because those patterns can be expressed without turning your component into a 700-line monument to pain.

For row actions, you typically render a custom cell (e.g., buttons) and keep business logic outside the table.
For selection, keep selected IDs in state. For remote data, keep page, pageSize, and sorting state in React,
then fetch on change—this is the most practical answer to “how do I build a React data grid-like experience without actually shipping a grid?”

Here’s a compact server-side pattern: when the user changes page or sorting, you call an API and update records plus totalRecords.
(The API bits are mocked—wire them to your backend.)

import React, { useEffect, useMemo, useState } from "react";
import { DataTable, type DataTableSortStatus } from "mantine-datatable";
import { Button, Group, Text } from "@mantine/core";

type User = { id: string; name: string; email: string; role: string };

async function fetchUsers(params: {
  page: number;
  pageSize: number;
  sortBy: string;
  sortDir: "asc" | "desc";
}): Promise<{ records: User[]; total: number }> {
  // Replace with a real request:
  // GET /api/users?page=...&pageSize=...&sortBy=...&sortDir=...
  await new Promise((r) => setTimeout(r, 350));
  return {
    records: [
      { id: "u_10", name: "Sam Lee", email: "sam@example.com", role: "Editor" }
      // ...
    ],
    total: 128,
  };
}

export default function UsersRemoteTable() {
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [totalRecords, setTotalRecords] = useState(0);
  const [records, setRecords] = useState<User[]>([]);
  const [fetching, setFetching] = useState(false);

  const [sortStatus, setSortStatus] = useState<DataTableSortStatus<User>>({
    columnAccessor: "name",
    direction: "asc",
  });

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setFetching(true);
      const res = await fetchUsers({
        page,
        pageSize,
        sortBy: String(sortStatus.columnAccessor),
        sortDir: sortStatus.direction,
      });
      if (!cancelled) {
        setRecords(res.records);
        setTotalRecords(res.total);
        setFetching(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [page, pageSize, sortStatus]);

  const columns = useMemo(
    () => [
      { accessor: "name", sortable: true },
      { accessor: "email" },
      { accessor: "role", sortable: true },
      {
        accessor: "actions",
        title: <Text size="sm">Actions</Text>,
        render: (user: User) => (
          <Group gap="xs">
            <Button size="xs" variant="light" onClick={() => alert(`View ${user.id}`)}>
              View
            </Button>
            <Button size="xs" color="red" variant="light" onClick={() => alert(`Delete ${user.id}`)}>
              Delete
            </Button>
          </Group>
        ),
      },
    ],
    []
  );

  return (
    <DataTable
      records={records}
      columns={columns}
      idAccessor="id"
      fetching={fetching}
      totalRecords={totalRecords}
      recordsPerPage={pageSize}
      page={page}
      onPageChange={setPage}
      onRecordsPerPageChange={setPageSize}
      recordsPerPageOptions={[10, 20, 50]}
      sortStatus={sortStatus}
      onSortStatusChange={setSortStatus}
      withTableBorder
      highlightOnHover
    />
  );
}

Two common “why is this not working?” pitfalls are worth calling out:

  • Unstable IDs: ensure idAccessor points to a unique, stable field (UUIDs or DB IDs).
  • Client-side everything: if you’re building admin panels, assume server-side pagination/sorting sooner rather than later.

Performance, UX polish, and “SEO” for developer-facing docs

Performance starts with not rendering what you don’t need. If your product owners ask for “show all 50,000 rows on one page,”
that’s not a table problem—it’s a requirements problem wearing a fake mustache. For large datasets, prefer server-side pagination,
sensible page sizes (20–100), and fast filters. This is the practical middle ground between a simple table and a full React data grid.

UX polish is where adoption happens: use loading states (fetching), design a clear empty state,
and render meaningful cells (badges for status, monospace for IDs, buttons for actions). Mantine makes those details cheap,
and that’s the main reason people search for React table with Mantine in the first place.

If this article is going on a docs site (yes, developer docs have SEO too), structure your headings around task intent:
“installation”, “setup”, “basic usage”, “example”, and “getting started”. Those phrases match how users speak into voice search:
“How do I install mantine datatable?” and “Show me a Mantine DataTable React example.” Answer those directly with short definitions,
then back them up with code that actually compiles.

For quick reference links while you work:
mantine-datatable on npm,
the GitHub repo,
and Mantine’s Table component docs.

FAQ

How do I install mantine-datatable in a React project?

Install it via npm/yarn/pnpm, then ensure Mantine is configured (wrap your app in MantineProvider and import Mantine styles).
After that, import DataTable from mantine-datatable and render it with records and columns.

Is Mantine DataTable a data grid (with virtualization) or a table component?

It’s primarily a table component for interactive UI (sorting, pagination, selection, actions). If you need heavy virtualization
for huge datasets in one scroll, plan for server-side pagination or evaluate a specialized grid. In many apps, server-side patterns
deliver “grid-like” usability without shipping a full grid.

How do I implement server-side pagination and sorting with Mantine DataTable?

Keep page, recordsPerPage, and sortStatus in state. When any of them changes, fetch data from your API,
then pass the returned records plus totalRecords to the table. This keeps the UI responsive and avoids loading
the entire dataset in the browser.