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.


Demo

Open StackblitzOpen Code SandboxOpen on GitHub

Rows per page

0-0 of 0

Source Code

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

View Extra Storybook Examples