MRT logoMaterial React Table

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

View Extra Storybook Examples