MRT logoMaterial React Table

React Query (Remote) Example

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

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

View Extra Storybook Examples