MRT logoMaterial React Table

    Pagination Feature Guide

    Client-side pagination is enabled by default in Material React Table. There are a number of ways to customize pagination, turn off pagination, or completely replace the built in pagination with your own manual or server-side pagination logic.

    Relevant Props

    #
    Prop Name
    Type
    Default Value
    More Info Links
    1
    boolean
    true

    No Description Provided... Yet...

    2
    () => MRT_RowModel<TData>

    No Description Provided... Yet...

    3
    boolean
    TanStack Table Pagination Docs

    Enables manual pagination. If this option is set to true, the table will not automatically paginate rows using getPaginationRowModel() and instead will expect you to manually paginate the rows before passing them to the table. This is useful if you are doing server-side pagination and aggregation.

    4
    Partial<TablePaginationProps> | ({ table }) => Partial<TablePaginationProps>
    Material UI TablePagination Props

    No Description Provided... Yet...

    5
    OnChangeFn<PaginationState>
    TanStack Table Pagination Docs

    If this function is provided, it will be called when the pagination state changes and you will be expected to manage the state yourself. You can pass the managed state back to the table via the tableOptions.state.pagination option.

    6
    number
    TanStack Table Pagination Docs

    When manually controlling pagination, you should supply a total pageCount value to the table if you know it. If you do not know how many pages there are, you can set this to -1.

    7
    boolean
    TanStack Table Expanding Docs

    If true expanded rows will be paginated along with the rest of the table (which means expanded rows may span multiple pages). If false expanded rows will not be considered for pagination (which means expanded rows will always render on their parents page. This also means more rows will be rendered than the set page size)

    8
    'bottom' | 'top' | 'both'

    No Description Provided... Yet...

    9
    number

    No Description Provided... Yet...

    Relevant State Options

    #
    State Option
    Type
    Default Value
    More Info Links
    1
    { pageIndex: number, pageSize: number }
    { pageIndex: 0, pageSize: 10 }
    TanStack Table Pagination Docs

    No Description Provided... Yet...

    Disable Pagination

    If you simply want to disable pagination, you can set the enablePagination prop to false. This will both hide the pagination controls and disable the pagination functionality.

    If you only want to disable the pagination logic, but still want to show and use the pagination controls, take a look down below at the Manual Pagination docs.

    <MaterialTable columns={columns} data={data} enablePagination={false} />

    Customize Pagination

    Customize Pagination Behavior

    There are a few props that you can use to customize the pagination behavior. The first one is autoResetPagination. This prop is true by default, and causes a table to automatically reset the table back to the first page whenever sorting, filtering, or grouping occurs. This makes sense for most use cases, but if you want to disable this behavior, you can set this prop to false.

    Next there is paginateExpandedRows, which works in conjunction expanding features. This prop is true by default, and forces the table to still only render the same number of rows per page that is set as the page size, even as sub-rows become expanded. However, this does cause expanded rows to sometimes not be on the same page as their parent row, so you can turn this off to keep sub rows with their parent row on the same page.

    Customize Pagination Components

    You can customize the pagination component with the muiTablePaginationProps prop to change things like the rowsPerPageOptions or whether or not to show the first and last page buttons, and more.

    <MaterialReactTable
    columns={columns}
    data={data}
    muiTablePaginationProps={{
    rowsPerPageOptions: [5, 10],
    showFirstLastPageButtons: false,
    }}
    />

    View all table pagination options that you can tweak in the Material UI Table Pagination API Docs.

    Manual or Server-Side Pagination

    Manual Pagination

    The default pagination features are client-side. This means you have to have all of your data fetched and stored in the table all at once. This may not be ideal for large datasets, but don't worry, Material React Table supports server-side pagination.

    When the manualPagination prop is set to true, Material React Table will assume that the data that is passed to the table already has had the pagination logic applied. Usually you would do this in your back-end logic.

    Override Page Count and Row Count

    If you are using manual pagination, the default page count and row count in the Material UI pagination component will be incorrect, as it is only derived from the number of rows provided in the client-side data prop. Luckily, you can override these values and set your own page count or row count in the pageCount and rowCount props.

    <MaterialTable
    columns={columns}
    data={data}
    manualPagination
    rowCount={data.meta.totalDBRowCount} //you can tell the pagination how many rows there are in your back-end data
    />

    Manage Pagination State

    For either client-side or server-side pagination, you may want to have access to the pagination state yourself. You can do this like so with state:

    //store pagination state in your own state
    const [pagination, setPagination] = useState({
    pageIndex: 0,
    pageSize: 5, //customize the default page size
    });
    useEffect(() => {
    //do something when the pagination state changes
    }, [pagination.pageIndex, pagination.pageSize]);
    return (
    <MaterialTable
    columns={columns}
    data={data}
    onPaginationChange={setPagination} //hoist pagination state to your state when it changes internally
    state={{ pagination }} //pass the pagination state to the table
    />
    );

    Alternatively, if all you care about is customizing the initial pagination state and don't need to react to its changes, like customizing the default page size or the page index, you can do that like so with initialState:

    <MaterialTable
    columns={columns}
    data={data}
    initialState={{ pagination: { pageSize: 25, pageIndex: 2 } }}
    />

    Here is the full Remote Data example showing off server-side filtering, pagination, and sorting.


    Demo

    Open Code SandboxOpen on GitHub
    First Name
    Last Name
    Address
    State
    Phone Number

    No records to display

    Rows per page

    0-0 of 0

    Source Code

    1import React, { FC, useEffect, useMemo, useState } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3import type {
    4 ColumnFiltersState,
    5 PaginationState,
    6 SortingState,
    7} from '@tanstack/react-table';
    8
    9type UserApiResponse = {
    10 data: Array<User>;
    11 meta: {
    12 totalRowCount: number;
    13 };
    14};
    15
    16type User = {
    17 firstName: string;
    18 lastName: string;
    19 address: string;
    20 state: string;
    21 phoneNumber: string;
    22};
    23
    24const Example: FC = () => {
    25 const [data, setData] = useState<User[]>([]);
    26 const [isError, setIsError] = useState(false);
    27 const [isLoading, setIsLoading] = useState(false);
    28 const [isRefetching, setIsRefetching] = useState(false);
    29 const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
    30 const [globalFilter, setGlobalFilter] = useState('');
    31 const [sorting, setSorting] = useState<SortingState>([]);
    32 const [pagination, setPagination] = useState<PaginationState>({
    33 pageIndex: 0,
    34 pageSize: 10,
    35 });
    36 const [rowCount, setRowCount] = useState(0);
    37
    38 //if you want to avoid useEffect, look at the React Query example instead
    39 useEffect(() => {
    40 const fetchData = async () => {
    41 if (!data.length) {
    42 setIsLoading(true);
    43 } else {
    44 setIsRefetching(true);
    45 }
    46
    47 const url = new URL('/api/data', 'https://www.material-react-table.com');
    48 url.searchParams.set(
    49 'start',
    50 `${pagination.pageIndex * pagination.pageSize}`,
    51 );
    52 url.searchParams.set('size', `${pagination.pageSize}`);
    53 url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));
    54 url.searchParams.set('globalFilter', globalFilter ?? '');
    55 url.searchParams.set('sorting', JSON.stringify(sorting ?? []));
    56
    57 try {
    58 const response = await fetch(url.href);
    59 const json = (await response.json()) as UserApiResponse;
    60 setData(json.data);
    61 setRowCount(json.meta.totalRowCount);
    62 } catch (error) {
    63 setIsError(true);
    64 console.error(error);
    65 return;
    66 }
    67 setIsError(false);
    68 setIsLoading(false);
    69 setIsRefetching(false);
    70 };
    71 fetchData();
    72 // eslint-disable-next-line react-hooks/exhaustive-deps
    73 }, [
    74 columnFilters,
    75 globalFilter,
    76 pagination.pageIndex,
    77 pagination.pageSize,
    78 sorting,
    79 ]);
    80
    81 const columns = useMemo<MRT_ColumnDef<User>[]>(
    82 () => [
    83 {
    84 accessorKey: 'firstName',
    85 header: 'First Name',
    86 },
    87 //column definitions...
    105 ],
    106 [],
    107 );
    108
    109 return (
    110 <MaterialReactTable
    111 columns={columns}
    112 data={data}
    113 enableRowSelection
    114 getRowId={(row) => row.phoneNumber}
    115 initialState={{ showColumnFilters: true }}
    116 manualFiltering
    117 manualPagination
    118 manualSorting
    119 muiToolbarAlertBannerProps={
    120 isError
    121 ? {
    122 color: 'error',
    123 children: 'Error loading data',
    124 }
    125 : undefined
    126 }
    127 onColumnFiltersChange={setColumnFilters}
    128 onGlobalFilterChange={setGlobalFilter}
    129 onPaginationChange={setPagination}
    130 onSortingChange={setSorting}
    131 rowCount={rowCount}
    132 state={{
    133 columnFilters,
    134 globalFilter,
    135 isLoading,
    136 pagination,
    137 showAlertBanner: isError,
    138 showProgressBars: isRefetching,
    139 sorting,
    140 }}
    141 />
    142 );
    143};
    144
    145export default Example;
    146

    View Extra Storybook Examples