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(66 '/api/data',67 process.env.NODE_ENV === 'production'68 ? 'https://www.material-react-table.com'69 : 'http://localhost:3000',70 );7172 //read our state and pass it to the API as query params73 fetchURL.searchParams.set(74 'start',75 `${pagination.pageIndex * pagination.pageSize}`,76 );77 fetchURL.searchParams.set('size', `${pagination.pageSize}`);78 fetchURL.searchParams.set('filters', JSON.stringify(columnFilters ?? []));79 fetchURL.searchParams.set('globalFilter', globalFilter ?? '');80 fetchURL.searchParams.set('sorting', JSON.stringify(sorting ?? []));8182 //use whatever fetch library you want, fetch, axios, etc83 const response = await fetch(fetchURL.href);84 const json = (await response.json()) as UserApiResponse;85 return json;86 },87 placeholderData: keepPreviousData, //don't go to 0 rows when refetching or paginating to next page88 });8990 const columns = useMemo<MRT_ColumnDef<User>[]>(91 //column definitions...125 );126127 const table = useMaterialReactTable({128 columns,129 data,130 initialState: { showColumnFilters: true },131 manualFiltering: true, //turn off built-in client-side filtering132 manualPagination: true, //turn off built-in client-side pagination133 manualSorting: true, //turn off built-in client-side sorting134 muiToolbarAlertBannerProps: isError135 ? {136 color: 'error',137 children: 'Error loading data',138 }139 : undefined,140 onColumnFiltersChange: setColumnFilters,141 onGlobalFilterChange: setGlobalFilter,142 onPaginationChange: setPagination,143 onSortingChange: setSorting,144 renderTopToolbarCustomActions: () => (145 <Tooltip arrow title="Refresh Data">146 <IconButton onClick={() => refetch()}>147 <RefreshIcon />148 </IconButton>149 </Tooltip>150 ),151 rowCount: meta?.totalRowCount ?? 0,152 state: {153 columnFilters,154 globalFilter,155 isLoading,156 pagination,157 showAlertBanner: isError,158 showProgressBars: isRefetching,159 sorting,160 },161 });162163 return <MaterialReactTable table={table} />;164};165166const queryClient = new QueryClient();167168const ExampleWithReactQueryProvider = () => (169 //App.tsx or AppProviders file. Don't just wrap this component with QueryClientProvider! Wrap your whole App!170 <QueryClientProvider client={queryClient}>171 <Example />172 </QueryClientProvider>173);174175export default ExampleWithReactQueryProvider;176
View Extra Storybook Examples