MRT logoMaterial React Table

Legacy V1 Docs

Remote Data Fetching Example

You will most likely be using a remote data source for your table, which is fully supported. Here is an example of data being fetched from a remote server but also filtered, paginated, and sorted on the server.

Also, be sure to check out the React Query Example, which is very similar to this one, except it uses react-query to simplify much of the state management needed for fetching data, so that you don't need to fetch from a useEffect hook.


Demo

Open StackblitzOpen Code SandboxOpen on GitHub

No records to display

Rows per page

0-0 of 0

Source Code

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

View Extra Storybook Examples