MRT logoMaterial React Table

    Sorting Feature Guide

    Material React Table supports almost any sorting scenario you may have. Client-side sorting is enabled by default, but you can opt to implement your own server-side sorting logic, or even replace the default client-side sorting with your own implementation.

    Relevant Props

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

    No Description Provided... Yet...

    2
    boolean

    No Description Provided... Yet...

    3
    boolean
    true

    No Description Provided... Yet...

    4

    No Description Provided... Yet...

    5

    No Description Provided... Yet...

    6

    No Description Provided... Yet...

    7

    No Description Provided... Yet...

    8

    No Description Provided... Yet...

    9

    No Description Provided... Yet...

    10

    No Description Provided... Yet...

    Relevant Column Options

    #
    Column Option
    Type
    Default Value
    More Info Links
    1
    boolean

    No Description Provided... Yet...

    2
    boolean

    No Description Provided... Yet...

    3
    boolean
    false

    No Description Provided... Yet...

    4
    boolean

    No Description Provided... Yet...

    5
    false | 1 | -1

    No Description Provided... Yet...

    6
    SortingFnOption

    No Description Provided... Yet...

    Relevant State Options

    #
    State Option
    Type
    Default Value
    More Info Links
    1
    Array<{ id: string, desc: boolean }>
    []
    TanStack Table Sorting Docs

    No Description Provided... Yet...

    Disable Sorting

    Sorting can be disabled globally by setting the enableSorting prop to false. This will disable sorting for all columns. You can also disable sorting for individual columns by setting the enableSorting column option to false.

    const columns = [
    {
    accessorKey: 'name',
    header: 'Name',
    enableSorting: false, // disable sorting for this column
    },
    ];
    return (
    <MaterialReactTable
    columns={columns}
    data={data}
    enableSorting={false} //disable sorting for all columns
    />
    );

    Default Sorting Features

    Client-side sorting is enabled by default. When sorting is toggled on for a column, the table will be sorted by an alphanumeric sorting algorithm by default.

    Multi-Sorting

    Multi-sorting is also enabled by default, which means a user can sort by multiple columns at once. This can be accomplished by clicking on a column header while holding down the shift key. The table will then be sorted by the previously sorted column, and then by the newly clicked column. You can limit the number of columns that can be sorted at once by setting the maxMultiSortColCount prop, or you can disable multi-sorting entirely by setting the enableMultiSort prop to false.

    Sort Direction

    By default, columns with string datatypes will sort alphabetically in ascending order, but columns with number datatypes will sort numerically in descending order. You can change the default sort direction per column by specifying the sortDescFirst column option to either true or false. You can also change the default sort direction globally by setting the sortDescFirst prop to either true or false.

    Sorting Functions

    By default, Material React Table will use an alphanumeric sorting function for all columns.

    There are 6 built-in sorting functions that you can choose from: alphanumeric, alphanumericCaseSensitive, text, textCaseSensitive, datetime, and basic. You can learn more about these built-in sorting function in the TanStack Table Sorting API docs.

    Add Custom Sorting Functions

    If none of these sorting functions meet your needs, you can add your own custom sorting functions by specifying more sorting functions in the sortingFns prop.

    <MaterialReactTable
    columns={columns}
    data={data}
    sortingFns={{
    //will add a new sorting function to the list of other sorting functions already available
    myCustomSortingFn: (rowA, rowB, columnId) => // your custom sorting logic
    }}
    />

    Change Sorting Function Per Column

    You can now choose a sorting function for each column by either passing a string value of the built-in sorting function names to the sortingFn column option, or by passing a custom sorting function to the sortingFn column option.

    const columns = [
    {
    accessorKey: 'name',
    header: 'Name',
    sortingFn: 'textCaseSensitive', //use the built-in textCaseSensitive sorting function instead of the default alphanumeric sorting function
    },
    {
    accessorKey: 'age',
    header: 'Age',
    //use your own custom sorting function instead of any of the built-in sorting functions
    sortingFn: (rowA, rowB, columnId) => // your custom sorting logic
    },
    ];

    Manual Server-Side Sorting

    If you are working with large data sets, you may want to let your back-end apis handle all of the sorting and pagination processing instead of doing it client-side. You can do this by setting the manualSorting prop to true. This will disable the default client-side sorting and pagination features, and will allow you to implement your own sorting and pagination logic.

    When manualSorting is set to true, Material React Table assumes that your data is already sorted by the time you are passing it to the table.

    If you need to sort your data in a back-end api, then you will also probably need access to the internal sorting state from the table. You can do this by managing the sorting state yourself, and then passing it to the table via the state prop. You can also pass a callback function to the onSortingChange prop, which will be called whenever the sorting state changes internally in the table

    const [sorting, setSorting] = useState({});
    useEffect(() => {
    //do something with the sorting state when it changes
    }, [sorting]);
    return (
    <MaterialReactTable
    columns={columns}
    data={data}
    manualSorting
    state={{ sorting }}
    onSortingChange={setSorting}
    />
    );

    Remote Sorting Example

    Here is the full Remote Data example showing how to implement server-side sorting, filtering, and pagination with Material React Table.


    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