Sorting and Filtering the Data Yourself
By default, the
<DataSource /> sorts and filters the data in the browser - for array data, for a Promise, for a data function, and also when sortInfo or filterValue are controlled.When you sort or filter the data yourself - on a server, in a data-fetching library like TanStack Query, or in your own code - tell the
<DataSource /> not to do it again, with shouldReloadData:<DataSource<Developer>
primaryKey="id"
data={rows}
sortInfo={sortInfo}
onSortInfoChange={setSortInfo}
filterValue={filterValue}
onFilterValueChange={setFilterValue}
shouldReloadData={{ sortInfo: true, filterValue: true }}
/> COPY
- with a
datafunction, it's called again on every sort or filter change, with thesortInfoandfilterValuein its params; - with array data, you pass a new array every time the sorting or the filtering changes (eg from
onSortInfoChangeandonFilterValueChange).
Either way, the rows are shown as they come in - they are not sorted or filtered again in the browser.
Grouping and pivoting are always done in the browser - unless you use
lazyLoad, where the server returns the groups.Reusing the built-in sorting and filtering#
To sort and filter the data the same way the
<DataSource /> does, use the functions it uses:multisort(sortInfo, array)- the built-in sorting for flat data (it sorts the array in place, so pass a copy);defaultFilterFunction(param)- the built-in column filtering for one row. It needs the row, its index, the array, the primary key, and the column filters with their filter types - the defaultfilterTypesare exported too.
import {
defaultFilterFunction,
filterTypes,
multisort,
} from '@infinite-table/infinite-react';
function sortAndFilter(rows, sortInfo, filterValue) {
const filtered = rows.filter((data, index, dataArray) =>
defaultFilterFunction({
data,
index,
dataArray,
primaryKey: data.id,
filterValue,
filterTypes,
}),
);
return multisort(sortInfo, filtered);
} COPY
If you configure custom
filterTypes on the <DataSource />, pass the same ones to defaultFilterFunction.With TanStack Query#
The query key includes the sorting and the filtering, so every change runs a new query. Thanks to
placeholderData: keepPreviousData, the previous rows stay on screen until the new ones arrive - and because the <DataSource /> doesn't sort or filter them itself, they don't change until the query resolves.View Mode
Fork Forkimport { DataSource, DataSourcePropFilterValue, DataSourceSingleSortInfo, InfiniteTable, InfiniteTableColumn, defaultFilterFunction, filterTypes, multisort, } from '@infinite-table/infinite-react'; import { QueryClient, QueryClientProvider, keepPreviousData, useQuery, } from '@tanstack/react-query'; import * as React from 'react'; type Developer = { id: number; firstName: string; country: string; stack: string; age: number; }; const developers: Developer[] = [ { id: 1, firstName: 'Bob', country: 'USA', stack: 'backend', age: 30 }, { id: 2, firstName: 'Alice', country: 'France', stack: 'frontend', age: 25 }, { id: 3, firstName: 'Carl', country: 'USA', stack: 'full-stack', age: 40 }, { id: 4, firstName: 'Dana', country: 'France', stack: 'backend', age: 35 }, { id: 5, firstName: 'Eve', country: 'Germany', stack: 'frontend', age: 28 }, { id: 6, firstName: 'Frank', country: 'Germany', stack: 'backend', age: 45 }, ]; // pretend this runs on a server: it filters and sorts the rows, // with the same functions the DataSource uses function fetchDevelopers( sortInfo: DataSourceSingleSortInfo<Developer>[], filterValue: DataSourcePropFilterValue<Developer>, ) { const filtered = developers.filter((data, index, dataArray) => defaultFilterFunction({ data, index, dataArray, primaryKey: data.id, filterValue, filterTypes, }), ); const rows = multisort(sortInfo, filtered); return new Promise<Developer[]>((resolve) => { setTimeout(() => resolve(rows), 600); }); } const columns: Record<string, InfiniteTableColumn<Developer>> = { firstName: { field: 'firstName', header: 'First name' }, country: { field: 'country' }, stack: { field: 'stack' }, age: { field: 'age', type: 'number' }, }; const queryClient = new QueryClient(); const noRows: Developer[] = []; function Developers() { const [sortInfo, setSortInfo] = React.useState< DataSourceSingleSortInfo<Developer>[] >([]); const [filterValue, setFilterValue] = React.useState< DataSourcePropFilterValue<Developer> >([]); const { data, isFetching } = useQuery({ queryKey: ['developers', sortInfo, filterValue], queryFn: () => fetchDevelopers(sortInfo, filterValue), placeholderData: keepPreviousData, }); return ( <> <p style={{ color: 'var(--infinite-cell-color)' }}> {isFetching ? 'Loading...' : 'Sort or filter a column'} </p> <DataSource<Developer> primaryKey="id" data={data ?? noRows} sortInfo={sortInfo} onSortInfoChange={setSortInfo} filterValue={filterValue} onFilterValueChange={setFilterValue} shouldReloadData={{ sortInfo: true, filterValue: true }} > <InfiniteTable<Developer> columns={columns} showColumnFilters /> </DataSource> </> ); } export default function App() { return ( <QueryClientProvider client={queryClient}> <Developers /> </QueryClientProvider>