Hooks for building lightweight, fast and extendable datagrids for React
—
React Table provides comprehensive filtering capabilities through column-level filters and global search functionality. The filtering system supports multiple filter types, custom filter functions, and both manual and automatic filtering modes.
Enables individual column filtering with customizable filter types and automatic state management.
/**
* Adds column filtering capabilities to the table
* @param hooks - Hook registration object
*/
function useFilters(hooks: Hooks): void;
interface FilterInstance {
/** Set filter value for a specific column */
setFilter: (columnId: string, filterValue: any) => void;
/** Set all column filters at once */
setAllFilters: (filters: Filter[]) => void;
/** Reset all filters to initial state */
resetFilters: () => void;
/** Rows before filtering was applied */
preFilteredRows: Row[];
/** Rows after column filtering */
filteredRows: Row[];
}
interface FilterColumnInstance {
/** Whether this column can be filtered */
canFilter: boolean;
/** Set this column's filter value */
setFilter: (filterValue: any) => void;
/** Current filter value for this column */
filterValue: any;
/** Rows before this column's filter was applied */
preFilteredRows: Row[];
/** Rows after this column's filter was applied */
filteredRows: Row[];
}
interface Filter {
/** Column ID to filter */
id: string;
/** Filter value */
value: any;
}Configuration Options:
interface FilterOptions {
/** Disable automatic filtering (handle filtering externally) */
manualFilters?: boolean;
/** Whether columns can be filtered by default */
defaultCanFilter?: boolean;
/** Disable all filtering */
disableFilters?: boolean;
/** Custom filter type definitions */
filterTypes?: Record<string, FilterFunction>;
/** Auto-reset filters when data changes */
autoResetFilters?: boolean;
/** Initial filter state */
initialState?: {
filters?: Filter[];
};
}
interface FilterFunction {
(rows: Row[], columnIds: string[], filterValue: any): Row[];
/** Function to determine when filter should be auto-removed */
autoRemove?: (filterValue: any, column?: Column) => boolean;
}Usage Example:
import React from 'react';
import { useTable, useFilters } from 'react-table';
function FilterableTable({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
setFilter,
setAllFilters,
} = useTable(
{
columns,
data,
defaultCanFilter: true, // Enable filtering for all columns
},
useFilters
);
return (
<div>
{/* Filter Controls */}
<div>
<input
placeholder="Filter by name..."
onChange={(e) => setFilter('name', e.target.value)}
/>
<button onClick={() => setAllFilters([])}>
Clear All Filters
</button>
</div>
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>
{column.render('Header')}
{/* Column Filter */}
<div>
{column.canFilter && (
<input
value={column.filterValue || ''}
onChange={(e) => column.setFilter(e.target.value)}
placeholder={`Filter ${column.render('Header')}`}
/>
)}
</div>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => (
<td {...cell.getCellProps()}>
{cell.render('Cell')}
</td>
))}
</tr>
);
})}
</tbody>
</table>
</div>
);
}Provides global search functionality that filters across all filterable columns.
/**
* Adds global filtering capabilities to the table
* @param hooks - Hook registration object
*/
function useGlobalFilter(hooks: Hooks): void;
interface GlobalFilterInstance {
/** Set the global filter value */
setGlobalFilter: (filterValue: any) => void;
/** Reset global filter to initial state */
resetGlobalFilter: () => void;
/** Rows before global filtering was applied */
preGlobalFilteredRows: Row[];
/** Rows after global filtering */
globalFilteredRows: Row[];
}Configuration Options:
interface GlobalFilterOptions {
/** Disable automatic global filtering */
manualGlobalFilter?: boolean;
/** Global filter function or filter type name */
globalFilter?: string | FilterFunction;
/** Disable global filtering entirely */
disableGlobalFilter?: boolean;
/** Auto-reset global filter when data changes */
autoResetGlobalFilter?: boolean;
/** Initial global filter state */
initialState?: {
globalFilter?: any;
};
}Usage Example:
import React from 'react';
import { useTable, useFilters, useGlobalFilter } from 'react-table';
function GloballyFilterableTable({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
setGlobalFilter,
preGlobalFilteredRows,
state: { globalFilter },
} = useTable(
{
columns,
data,
},
useFilters,
useGlobalFilter
);
return (
<div>
{/* Global Search */}
<div>
<input
value={globalFilter || ''}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder={`Search ${preGlobalFilteredRows.length} records...`}
/>
</div>
<table {...getTableProps()}>
{/* Table implementation */}
</table>
</div>
);
}React Table includes several built-in filter functions for common use cases.
interface FilterTypes {
/** Case-insensitive text contains filter */
text: FilterFunction;
/** Case-insensitive exact text match */
exactText: FilterFunction;
/** Case-sensitive exact text match */
exactTextCase: FilterFunction;
/** Array includes value filter */
includes: FilterFunction;
/** Array includes all values filter */
includesAll: FilterFunction;
/** Array includes some values filter */
includesSome: FilterFunction;
/** Value included in array filter */
includesValue: FilterFunction;
/** Strict equality filter */
exact: FilterFunction;
/** Loose equality filter */
equals: FilterFunction;
/** Numeric range filter */
between: FilterFunction;
}Filter Type Examples:
const columns = [
{
Header: 'Name',
accessor: 'name',
filter: 'text', // Case-insensitive contains
},
{
Header: 'Status',
accessor: 'status',
filter: 'exactText', // Exact match
},
{
Header: 'Age',
accessor: 'age',
filter: 'between', // Numeric range
Filter: ({ column: { filterValue = [], setFilter } }) => (
<div>
<input
value={filterValue[0] || ''}
type="number"
onChange={(e) => setFilter([e.target.value, filterValue[1]])}
placeholder="Min"
/>
<input
value={filterValue[1] || ''}
type="number"
onChange={(e) => setFilter([filterValue[0], e.target.value])}
placeholder="Max"
/>
</div>
),
},
{
Header: 'Tags',
accessor: 'tags',
filter: 'includesSome', // Array intersection
},
];Create custom filter logic for specialized filtering needs.
/**
* Custom filter function signature
* @param rows - Array of rows to filter
* @param columnIds - Array of column IDs being filtered
* @param filterValue - The filter value
* @returns Filtered array of rows
*/
interface CustomFilterFunction {
(rows: Row[], columnIds: string[], filterValue: any): Row[];
/** Auto-removal logic */
autoRemove?: (filterValue: any, column?: Column) => boolean;
}Custom Filter Examples:
// Custom filter for date ranges
const dateRangeFilter = (rows, columnIds, filterValue) => {
const [startDate, endDate] = filterValue || [];
if (!startDate && !endDate) return rows;
return rows.filter(row => {
return columnIds.some(columnId => {
const cellValue = row.values[columnId];
const date = new Date(cellValue);
if (startDate && date < new Date(startDate)) return false;
if (endDate && date > new Date(endDate)) return false;
return true;
});
});
};
// Auto-remove when both dates are empty
dateRangeFilter.autoRemove = (value) => {
return !value || (!value[0] && !value[1]);
};
// Custom filter for fuzzy matching
const fuzzyTextFilter = (rows, columnIds, filterValue) => {
const searchTerm = filterValue.toLowerCase();
return rows.filter(row => {
return columnIds.some(columnId => {
const cellValue = String(row.values[columnId]).toLowerCase();
// Simple fuzzy matching: allow 1 character difference per 4 characters
const maxDistance = Math.floor(searchTerm.length / 4);
return levenshteinDistance(cellValue, searchTerm) <= maxDistance;
});
});
};
fuzzyTextFilter.autoRemove = val => !val;
// Register custom filters
const table = useTable(
{
columns,
data,
filterTypes: {
dateRange: dateRangeFilter,
fuzzy: fuzzyTextFilter,
},
},
useFilters
);Configure filtering behavior at the column level.
interface ColumnFilterConfig {
/** Filter type name or custom filter function */
filter?: string | FilterFunction;
/** Whether this column can be filtered */
disableFilters?: boolean;
/** Custom Filter component for UI */
Filter?: React.ComponentType<{
column: Column;
filterValue: any;
setFilter: (value: any) => void;
preFilteredRows: Row[];
}>;
}Column Filter Examples:
const columns = [
{
Header: 'Product Name',
accessor: 'name',
filter: 'text',
// Custom filter UI component
Filter: ({ column: { filterValue, setFilter, preFilteredRows } }) => {
const count = preFilteredRows.length;
return (
<input
value={filterValue || ''}
onChange={(e) => setFilter(e.target.value || undefined)}
placeholder={`Search ${count} products...`}
/>
);
},
},
{
Header: 'Category',
accessor: 'category',
filter: 'exactText',
// Dropdown filter
Filter: ({ column: { filterValue, setFilter, preFilteredRows } }) => {
const options = React.useMemo(() => {
const opts = new Set();
preFilteredRows.forEach(row => opts.add(row.values.category));
return [...opts.values()];
}, [preFilteredRows]);
return (
<select
value={filterValue || ''}
onChange={(e) => setFilter(e.target.value || undefined)}
>
<option value="">All</option>
{options.map(option => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
);
},
},
{
Header: 'Price',
accessor: 'price',
disableFilters: true, // Disable filtering for this column
},
];Take control of filtering logic for server-side or custom implementations.
function ManuallyFilteredTable({ columns, data }) {
const [filters, setFilters] = React.useState([]);
const [globalFilter, setGlobalFilter] = React.useState('');
// Fetch filtered data based on current filters
const filteredData = React.useMemo(() => {
return fetchFilteredData(data, filters, globalFilter);
}, [data, filters, globalFilter]);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable(
{
columns,
data: filteredData,
manualFilters: true, // Disable automatic filtering
manualGlobalFilter: true,
// Provide current filter state
state: {
filters,
globalFilter,
},
},
useFilters,
useGlobalFilter
);
return (
<div>
<input
value={globalFilter}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Global search..."
/>
<table {...getTableProps()}>
{/* Table implementation */}
</table>
</div>
);
}interface TableState {
/** Column filter configurations */
filters: Filter[];
/** Global filter value */
globalFilter: any;
}
interface Filter {
/** Column ID */
id: string;
/** Filter value */
value: any;
}
interface FilterMeta {
instance: TableInstance;
column: Column;
}Install with Tessl CLI
npx tessl i tessl/npm-react-table