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 { 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 'table-data',58 columnFilters, //refetch when columnFilters changes59 globalFilter, //refetch when globalFilter changes60 pagination.pageIndex, //refetch when pagination.pageIndex changes61 pagination.pageSize, //refetch when pagination.pageSize changes62 sorting, //refetch when sorting changes63 ],64 queryFn: async () => {65 const fetchURL = new URL('/api/data', location.origin);6667 //read our state and pass it to the API as query params68 fetchURL.searchParams.set(69 'start',70 `${pagination.pageIndex * pagination.pageSize}`,71 );72 fetchURL.searchParams.set('size', `${pagination.pageSize}`);73 fetchURL.searchParams.set('filters', JSON.stringify(columnFilters ?? []));74 fetchURL.searchParams.set('globalFilter', globalFilter ?? '');75 fetchURL.searchParams.set('sorting', JSON.stringify(sorting ?? []));7677 //use whatever fetch library you want, fetch, axios, etc78 const response = await fetch(fetchURL.href);79 const json = (await response.json()) as UserApiResponse;80 return json;81 },82 placeholderData: keepPreviousData, //don't go to 0 rows when refetching or paginating to next page83 });8485 const columns = useMemo<MRT_ColumnDef<User>[]>(86 //column definitions...120 );121122 const table = useMaterialReactTable({123 columns,124 data,125 initialState: { showColumnFilters: true },126 manualFiltering: true, //turn off built-in client-side filtering127 manualPagination: true, //turn off built-in client-side pagination128 manualSorting: true, //turn off built-in client-side sorting129 muiToolbarAlertBannerProps: isError130 ? {131 color: 'error',132 children: 'Error loading data',133 }134 : undefined,135 onColumnFiltersChange: setColumnFilters,136 onGlobalFilterChange: setGlobalFilter,137 onPaginationChange: setPagination,138 onSortingChange: setSorting,139 renderTopToolbarCustomActions: () => (140 <Tooltip arrow title="Refresh Data">141 <IconButton onClick={() => refetch()}>142 <RefreshIcon />143 </IconButton>144 </Tooltip>145 ),146 rowCount: meta?.totalRowCount ?? 0,147 state: {148 columnFilters,149 globalFilter,150 isLoading,151 pagination,152 showAlertBanner: isError,153 showProgressBars: isRefetching,154 sorting,155 },156 });157158 return <MaterialReactTable table={table} />;159};160161const queryClient = new QueryClient();162163const ExampleWithReactQueryProvider = () => (164 //App.tsx or AppProviders file. Don't just wrap this component with QueryClientProvider! Wrap your whole App!165 <QueryClientProvider client={queryClient}>166 <Example />167 </QueryClientProvider>168);169170export default ExampleWithReactQueryProvider;171
View Extra Storybook Examples