MRT logoMaterial React Table

Legacy V1 Docs

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

View Extra Storybook Examples