MRT logoMaterial React Table

Remote Data Example

More than likely you will be using a remote data source for your table. This is fully supported. Here is an example where data is fetched from a remote server, but also filtered, paginated, and sorted on the server.

Also be sure to check out the TanStack React Query Example which is very similar to this one, but uses react-query to simplify much of the state management needed for fetching data.


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