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.
First Name | Last Name | Address | State | Phone Number | Last Login |
---|---|---|---|---|---|
10
1import { lazy, Suspense, useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6 type MRT_ColumnFiltersState,7 type MRT_PaginationState,8 type MRT_SortingState,9} from 'material-react-table';10import { IconButton, Tooltip } from '@mui/material';11import RefreshIcon from '@mui/icons-material/Refresh';12import {13 QueryClient,14 QueryClientProvider,15 keepPreviousData,16 useQuery,17} from '@tanstack/react-query'; //note: this is TanStack React Query V51819//Your API response shape will probably be different. Knowing a total row count is important though.20type UserApiResponse = {21 data: Array<User>;22 meta: {23 totalRowCount: number;24 };25};2627type User = {28 firstName: string;29 lastName: string;30 address: string;31 state: string;32 phoneNumber: string;33 lastLogin: Date;34};3536const Example = () => {37 //manage our own state for stuff we want to pass to the API38 const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(39 [],40 );41 const [globalFilter, setGlobalFilter] = useState('');42 const [sorting, setSorting] = useState<MRT_SortingState>([]);43 const [pagination, setPagination] = useState<MRT_PaginationState>({44 pageIndex: 0,45 pageSize: 10,46 });4748 //consider storing this code in a custom hook (i.e useFetchUsers)49 const {50 data: { data = [], meta } = {}, //your data and api response will probably be different51 isError,52 isRefetching,53 isLoading,54 refetch,55 } = useQuery<UserApiResponse>({56 queryKey: [57 'users-list',58 {59 columnFilters, //refetch when columnFilters changes60 globalFilter, //refetch when globalFilter changes61 pagination, //refetch when pagination changes62 sorting, //refetch when sorting changes63 },64 ],65 queryFn: async () => {66 const fetchURL = new URL('/api/data', location.origin);6768 //read our state and pass it to the API as query params69 fetchURL.searchParams.set(70 'start',71 `${pagination.pageIndex * pagination.pageSize}`,72 );73 fetchURL.searchParams.set('size', `${pagination.pageSize}`);74 fetchURL.searchParams.set('filters', JSON.stringify(columnFilters ?? []));75 fetchURL.searchParams.set('globalFilter', globalFilter ?? '');76 fetchURL.searchParams.set('sorting', JSON.stringify(sorting ?? []));7778 //use whatever fetch library you want, fetch, axios, etc79 const response = await fetch(fetchURL.href);80 const json = (await response.json()) as UserApiResponse;81 return json;82 },83 placeholderData: keepPreviousData, //don't go to 0 rows when refetching or paginating to next page84 });8586 const columns = useMemo<MRT_ColumnDef<User>[]>(87 //column definitions...121 );122123 const table = useMaterialReactTable({124 columns,125 data,126 initialState: { showColumnFilters: true },127 manualFiltering: true, //turn off built-in client-side filtering128 manualPagination: true, //turn off built-in client-side pagination129 manualSorting: true, //turn off built-in client-side sorting130 muiToolbarAlertBannerProps: isError131 ? {132 color: 'error',133 children: 'Error loading data',134 }135 : undefined,136 onColumnFiltersChange: setColumnFilters,137 onGlobalFilterChange: setGlobalFilter,138 onPaginationChange: setPagination,139 onSortingChange: setSorting,140 renderTopToolbarCustomActions: () => (141 <Tooltip arrow title="Refresh Data">142 <IconButton onClick={() => refetch()}>143 <RefreshIcon />144 </IconButton>145 </Tooltip>146 ),147 rowCount: meta?.totalRowCount ?? 0,148 state: {149 columnFilters,150 globalFilter,151 isLoading,152 pagination,153 showAlertBanner: isError,154 showProgressBars: isRefetching,155 sorting,156 },157 });158159 return <MaterialReactTable table={table} />;160};161162//react query setup in App.tsx163const ReactQueryDevtoolsProduction = lazy(() =>164 import('@tanstack/react-query-devtools/build/modern/production.js').then(165 (d) => ({166 default: d.ReactQueryDevtools,167 }),168 ),169);170171const queryClient = new QueryClient();172173export default function App() {174 return (175 <QueryClientProvider client={queryClient}>176 <Example />177 <Suspense fallback={null}>178 <ReactQueryDevtoolsProduction />179 </Suspense>180 </QueryClientProvider>181 );182}183
View Extra Storybook Examples