MRT logoMaterial React Table

React Query (Remote) Example

This is just like the Remote Data Fetching Example, but react-query is used to simplify all the state management of the fetching and loading of data.

React Query is by far the best way to fetch remote data in React. It has features like caching, refetching, polling, pagination, and more that work together very well with table logic as seen in this example.

Also, be sure to check out the Virtualized Example, which shows off the use of another TanStack library, React Virtual, to render thousands of rows at once while still maintaining great performance.

CRUD Examples
More Examples

Demo

Open StackblitzOpen Code SandboxOpen on GitHub
0-0 of 0

Source Code

1import { 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';
9import { IconButton, Tooltip } from '@mui/material';
10import RefreshIcon from '@mui/icons-material/Refresh';
11import {
12 QueryClient,
13 QueryClientProvider,
14 keepPreviousData,
15 useQuery,
16} from '@tanstack/react-query';
17
18type UserApiResponse = {
19 data: Array<User>;
20 meta: {
21 totalRowCount: number;
22 };
23};
24
25type User = {
26 firstName: string;
27 lastName: string;
28 address: string;
29 state: string;
30 phoneNumber: string;
31};
32
33const Example = () => {
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 const { data, isError, isRefetching, isLoading, refetch } =
45 useQuery<UserApiResponse>({
46 queryKey: [
47 'table-data',
48 columnFilters, //refetch when columnFilters changes
49 globalFilter, //refetch when globalFilter changes
50 pagination.pageIndex, //refetch when pagination.pageIndex changes
51 pagination.pageSize, //refetch when pagination.pageSize changes
52 sorting, //refetch when sorting changes
53 ],
54 queryFn: async () => {
55 const fetchURL = new URL(
56 '/api/data',
57 process.env.NODE_ENV === 'production'
58 ? 'https://www.material-react-table.com'
59 : 'http://localhost:3000',
60 );
61 fetchURL.searchParams.set(
62 'start',
63 `${pagination.pageIndex * pagination.pageSize}`,
64 );
65 fetchURL.searchParams.set('size', `${pagination.pageSize}`);
66 fetchURL.searchParams.set(
67 'filters',
68 JSON.stringify(columnFilters ?? []),
69 );
70 fetchURL.searchParams.set('globalFilter', globalFilter ?? '');
71 fetchURL.searchParams.set('sorting', JSON.stringify(sorting ?? []));
72
73 const response = await fetch(fetchURL.href);
74 const json = (await response.json()) as UserApiResponse;
75 return json;
76 },
77 placeholderData: keepPreviousData,
78 });
79
80 const columns = useMemo<MRT_ColumnDef<User>[]>(
81 () => [
82 {
83 accessorKey: 'firstName',
84 header: 'First Name',
85 },
86 {
87 accessorKey: 'lastName',
88 header: 'Last Name',
89 },
90 {
91 accessorKey: 'address',
92 header: 'Address',
93 },
94 {
95 accessorKey: 'state',
96 header: 'State',
97 },
98 {
99 accessorKey: 'phoneNumber',
100 header: 'Phone Number',
101 },
102 ],
103 [],
104 );
105
106 return (
107 <MaterialReactTable
108 columns={columns}
109 data={data?.data ?? []} //data is undefined on first render
110 initialState={{ showColumnFilters: true }}
111 manualFiltering
112 manualPagination
113 manualSorting
114 muiToolbarAlertBannerProps={
115 isError
116 ? {
117 color: 'error',
118 children: 'Error loading data',
119 }
120 : undefined
121 }
122 onColumnFiltersChange={setColumnFilters}
123 onGlobalFilterChange={setGlobalFilter}
124 onPaginationChange={setPagination}
125 onSortingChange={setSorting}
126 renderTopToolbarCustomActions={() => (
127 <Tooltip arrow title="Refresh Data">
128 <IconButton onClick={() => refetch()}>
129 <RefreshIcon />
130 </IconButton>
131 </Tooltip>
132 )}
133 rowCount={data?.meta?.totalRowCount ?? 0}
134 state={{
135 columnFilters,
136 globalFilter,
137 isLoading,
138 pagination,
139 showAlertBanner: isError,
140 showProgressBars: isRefetching,
141 sorting,
142 }}
143 />
144 );
145};
146
147const queryClient = new QueryClient();
148
149const ExampleWithReactQueryProvider = () => (
150 //App.tsx or AppProviders file
151 <QueryClientProvider client={queryClient}>
152 <Example />
153 </QueryClientProvider>
154);
155
156export default ExampleWithReactQueryProvider;
157

View Extra Storybook Examples