Mantine React Table

repository·v2·Indexed 11 days ago

https://github.com/KevinVandy/mantine-react-table

A powerful, highly customizable data table library for React, built on top of Mantine V7 and TanStack Table V8. It provides a rich set of features including sorting, filtering, grouping, and editing out of the box.

Tokens
83K
Snippets
303
Records
387
Agent score
69%

What's inside Mantine React Table

  1. What is Mantine React Table?

    v2

    Mantine React Table (MRT) is a fully-featured data grid/table component library for React built on the TanStack Table V8 API. It is designed to work seamlessly in projects already using Mantine, though it is not strictly required.

    Key Requirements: To function correctly, MRT requires the following as peer dependencies:

    Developer Experience: MRT is built with TypeScript and uses advanced generics that react to your data structures. While TypeScript is optional, it is highly recommended for a faster developer experience, particularly when defining columns.

  2. Mantine React Table Features Overview

    v2

    Mantine React Table provides a wide range of built-in features that can be easily enabled or disabled.

    Core Capabilities:

    • Data Manipulation: Sorting, Filtering (client and server-side), Pagination, Global Filtering, and Data Editing (4 modes).
    • Column Management: Column Hiding, Ordering (Drag'n'Drop), Pinning (Freeze), Resizing, and Column Action Dropdowns.
    • Row Management: Row Selection (Checkboxes), Row Ordering (Drag'n'Drop), Row Actions, and Row Numbers.
    • Advanced Data Handling: Aggregation and Grouping (Sum, Average, Count, etc.), Tree Data (Expanding Sub-rows), and Virtualization (via @tanstack/react-virtual).
    • UI/UX: Detail Panels (Expansion), Density Toggle, Full Screen Mode, Click To Copy Cell Values, and Localization (i18n).
    • Integration: SSR compatible, Theming (respects Mantine Theme), and Toolbars for custom action buttons.
  3. Control Loading UI via State Options

    v2

    You can control the visibility of specific loading components using the following state options. This is useful when integrating with libraries like React Query to distinguish between initial data fetching, background pagination fetching, or mutations (saving data).

    State OptionDescription
    isLoadingTriggers the default loading overlay with cell skeletons.
    showLoadingOverlayControls the visibility of the loading overlay.
    showSkeletonsControls the visibility of cell skeletons.
    showProgressBarsControls the visibility of progress bars.
    isSavingIndicates if a saving operation is in progress.

    Example of granular control:

    const table = useMantineReactTable({
      columns,
      data: data ?? [],
      state: {
        // fetching next page pagination
        showLoadingOverlay: isFetching && isPreviousData, 
        // loading for the first time with no data
        showSkeletons: isLoading, 
        // from a mutation
        showProgressBars: isSavingUser, 
      },
    });
  4. Reduce bundle size by using sub-components

    v2

    Instead of importing the full <MantineReactTable /> component, which includes all toolbar components and advanced features, you can import smaller sub-components to reduce the amount of React code included in your bundle. This is useful when you only need the core table functionality without the extra UI elements.

    Available sub-components include:

    • <MRT_TableContainer />
    • <MRT_Table />
  5. Configure Filtering for Sub-Rows

    v2

    When using filtering with tree data, you can customize how the hierarchy responds to filters:

    Filter From Leaf Rows

    By default, filtering is top-down (if a parent is filtered out, all children are hidden). Setting filterFromLeafRows: true changes this to bottom-up: a parent row will remain visible as long as at least one of its descendants matches the filter.

    Max Leaf Row Filter Depth

    Controls how deep the filtering logic applies.

    • maxLeafRowFilterDepth: 0: Filtering only applies to root-level rows. If a root row matches, all its children are shown regardless of whether the children match the filter.
    • maxLeafRowFilterDepth: 1: Filtering applies to children (1 level deep).
    // Filter from leaf rows up
    const table = useMantineReactTable({
      columns,
      data,
      enableExpanding: true,
      filterFromLeafRows: true,
    });
    
    // Only filter root rows, keep all children of matching parents visible
    const table = useMantineReactTable({
      columns,
      data,
      enableExpanding: true,
      maxLeafRowFilterDepth: 0,
    });
  6. Use Original Row Numbers

    v2

    In original mode, row numbers are linked to the original index of the data array. This means the row number is tied to the specific data record. When you sort, filter, or search the table, the row numbers will move with their corresponding rows, preserving the identity of the data's original position.

    const table = useMantineReactTable({
      columns,
      data,
      enableRowNumbers: true,
      rowNumberDisplayMode: 'original',
    });
  7. Use faceted values for automatic filter suggestions

    v2

    Mantine React Table can leverage the faceted values feature from TanStack Table to automatically scan your data and generate UI elements for column filters. This allows you to automatically populate:

    • Filter autocomplete suggestions
    • Filter select options
    • Min and max values for numeric column filters

    This feature is part of the broader Column Filtering functionality. For detailed implementation details on how to configure these filters, refer to the Column Filtering Feature Guide.

  8. Define and memoize table data

    v2

    Data must be an array of objects where the object properties match the accessorKey or accessorFn in your column definitions.

    Critical Requirement: The data array must be memoized or stable (e.g., using useState, useMemo, or defined outside the component). If the data is recreated on every render, it can cause infinite re-render loops.

    While nested data is supported, a flat object structure is recommended for easier column configuration.

    // Recommended flat structure
    // Must be memoized or stable
    const data = [
      {
        name: 'John',
        age: 30,
      },
      {
        name: 'Sara',
        age: 25,
      },
    ];
  9. Access Column Instance APIs

    v2

    In Mantine React Table, every column has an associated column instance object. This object provides access to various static methods and properties that describe the state and definition of that specific column.

    Important Distinction: These are not column options (configuration settings). They are methods and properties available on the instance itself to inspect or react to the column's current state.

    Common Access Points

    You can access the column instance in several callback props and component overrides:

    1. Column Definition Callbacks: Inside properties like mantineTableHeadCellProps, Header, or Cell within your column array.
    2. Table Instance Callbacks: Inside global table callback props like mantineTableBodyCellProps provided to useMantineReactTable.
    const columns = [
      {
        accessorKey: 'username',
        header: 'Username',
        // Accessing column instance in a column definition callback
        mantineTableHeadCellProps: ({ column }) => ({
          style: {
            color: column.getIsSorted() ? 'red' : 'black',
          },
        }),
        // Accessing column instance in the Header component override
        Header: ({ column }) => <div>{column.columnDef.header}</div>,
        // Accessing column instance in the Cell component override
        Cell: ({ cell, column }) => (
          <Box
            style={{
              backgroundColor: column.getIsGrouped() ? 'green' : 'white',
            }}
          >
            {cell.getValue()}
          </Box>
        ),
      },
    ];
    
    const table = useMantineReactTable({
      columns,
      data,
      // Accessing column instance in table-level callback props
      mantineTableBodyCellProps: ({ column }) => ({
        style: {
          boxShadow: column.getIsPinned() ? '0 0 0 2px red' : 'none',
        },
      }),
    });
  10. What are Display Columns in Mantine React Table

    v2

    Display columns are used to render non-data elements within a table (e.g., row selection, row actions, or custom buttons). Unlike data columns, they do not connect to your data source and therefore do not require an accessorKey or accessorFn. They only require an id and a header.

    By default, display columns have all processing features disabled, including:

    • Sorting
    • Filtering
    • Grouping
    • Resizing
    • Column ordering/dragging
    • Column actions
    • Global filtering
    • Hiding
  11. Create re-usable MRT configurations via default options

    v2

    Instead of wrapping the entire table in a custom component, the recommended best practice for re-usability is to define a factory function that returns default MRT_TableOptions<TData>. This allows you to share common settings (like pagination modes or global filter settings) while maintaining full control over the table instance and state in each specific component.

    import { type MRT_RowData, type MRT_TableOptions } from 'mantine-react-table';
    
    export const getDefaultMRTOptions = <TData extends MRT_RowData>(): Partial<MRT_TableOptions<TData>> => ({
      enableGlobalFilter: false,
      enableRowPinning: true,
      initialState: { showColumnFilters: true },
      manualFiltering: true,
      manualPagination: true,
      manualSorting: true,
      paginationDisplayMode: 'pages',
    });
    
    // Usage in a component
    const defaultMRTOptions = getDefaultMRTOptions<User>();
    const table = useMantineReactTable({
      ...defaultMRTOptions,
      columns,
      data,
      enableGlobalFilter: true, // override
      initialState: {
        ...defaultMRTOptions.initialState,
        showColumnFilters: false, // override nested state
      },
    });