0
# Data Filtering
1
2
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.
3
4
## Capabilities
5
6
### Column Filters (useFilters)
7
8
Enables individual column filtering with customizable filter types and automatic state management.
9
10
```javascript { .api }
11
/**
12
* Adds column filtering capabilities to the table
13
* @param hooks - Hook registration object
14
*/
15
function useFilters(hooks: Hooks): void;
16
17
interface FilterInstance {
18
/** Set filter value for a specific column */
19
setFilter: (columnId: string, filterValue: any) => void;
20
/** Set all column filters at once */
21
setAllFilters: (filters: Filter[]) => void;
22
/** Reset all filters to initial state */
23
resetFilters: () => void;
24
/** Rows before filtering was applied */
25
preFilteredRows: Row[];
26
/** Rows after column filtering */
27
filteredRows: Row[];
28
}
29
30
interface FilterColumnInstance {
31
/** Whether this column can be filtered */
32
canFilter: boolean;
33
/** Set this column's filter value */
34
setFilter: (filterValue: any) => void;
35
/** Current filter value for this column */
36
filterValue: any;
37
/** Rows before this column's filter was applied */
38
preFilteredRows: Row[];
39
/** Rows after this column's filter was applied */
40
filteredRows: Row[];
41
}
42
43
interface Filter {
44
/** Column ID to filter */
45
id: string;
46
/** Filter value */
47
value: any;
48
}
49
```
50
51
**Configuration Options:**
52
53
```javascript { .api }
54
interface FilterOptions {
55
/** Disable automatic filtering (handle filtering externally) */
56
manualFilters?: boolean;
57
/** Whether columns can be filtered by default */
58
defaultCanFilter?: boolean;
59
/** Disable all filtering */
60
disableFilters?: boolean;
61
/** Custom filter type definitions */
62
filterTypes?: Record<string, FilterFunction>;
63
/** Auto-reset filters when data changes */
64
autoResetFilters?: boolean;
65
/** Initial filter state */
66
initialState?: {
67
filters?: Filter[];
68
};
69
}
70
71
interface FilterFunction {
72
(rows: Row[], columnIds: string[], filterValue: any): Row[];
73
/** Function to determine when filter should be auto-removed */
74
autoRemove?: (filterValue: any, column?: Column) => boolean;
75
}
76
```
77
78
**Usage Example:**
79
80
```javascript
81
import React from 'react';
82
import { useTable, useFilters } from 'react-table';
83
84
function FilterableTable({ columns, data }) {
85
const {
86
getTableProps,
87
getTableBodyProps,
88
headerGroups,
89
rows,
90
prepareRow,
91
setFilter,
92
setAllFilters,
93
} = useTable(
94
{
95
columns,
96
data,
97
defaultCanFilter: true, // Enable filtering for all columns
98
},
99
useFilters
100
);
101
102
return (
103
<div>
104
{/* Filter Controls */}
105
<div>
106
<input
107
placeholder="Filter by name..."
108
onChange={(e) => setFilter('name', e.target.value)}
109
/>
110
<button onClick={() => setAllFilters([])}>
111
Clear All Filters
112
</button>
113
</div>
114
115
<table {...getTableProps()}>
116
<thead>
117
{headerGroups.map(headerGroup => (
118
<tr {...headerGroup.getHeaderGroupProps()}>
119
{headerGroup.headers.map(column => (
120
<th {...column.getHeaderProps()}>
121
{column.render('Header')}
122
{/* Column Filter */}
123
<div>
124
{column.canFilter && (
125
<input
126
value={column.filterValue || ''}
127
onChange={(e) => column.setFilter(e.target.value)}
128
placeholder={`Filter ${column.render('Header')}`}
129
/>
130
)}
131
</div>
132
</th>
133
))}
134
</tr>
135
))}
136
</thead>
137
<tbody {...getTableBodyProps()}>
138
{rows.map(row => {
139
prepareRow(row);
140
return (
141
<tr {...row.getRowProps()}>
142
{row.cells.map(cell => (
143
<td {...cell.getCellProps()}>
144
{cell.render('Cell')}
145
</td>
146
))}
147
</tr>
148
);
149
})}
150
</tbody>
151
</table>
152
</div>
153
);
154
}
155
```
156
157
### Global Filter (useGlobalFilter)
158
159
Provides global search functionality that filters across all filterable columns.
160
161
```javascript { .api }
162
/**
163
* Adds global filtering capabilities to the table
164
* @param hooks - Hook registration object
165
*/
166
function useGlobalFilter(hooks: Hooks): void;
167
168
interface GlobalFilterInstance {
169
/** Set the global filter value */
170
setGlobalFilter: (filterValue: any) => void;
171
/** Reset global filter to initial state */
172
resetGlobalFilter: () => void;
173
/** Rows before global filtering was applied */
174
preGlobalFilteredRows: Row[];
175
/** Rows after global filtering */
176
globalFilteredRows: Row[];
177
}
178
```
179
180
**Configuration Options:**
181
182
```javascript { .api }
183
interface GlobalFilterOptions {
184
/** Disable automatic global filtering */
185
manualGlobalFilter?: boolean;
186
/** Global filter function or filter type name */
187
globalFilter?: string | FilterFunction;
188
/** Disable global filtering entirely */
189
disableGlobalFilter?: boolean;
190
/** Auto-reset global filter when data changes */
191
autoResetGlobalFilter?: boolean;
192
/** Initial global filter state */
193
initialState?: {
194
globalFilter?: any;
195
};
196
}
197
```
198
199
**Usage Example:**
200
201
```javascript
202
import React from 'react';
203
import { useTable, useFilters, useGlobalFilter } from 'react-table';
204
205
function GloballyFilterableTable({ columns, data }) {
206
const {
207
getTableProps,
208
getTableBodyProps,
209
headerGroups,
210
rows,
211
prepareRow,
212
setGlobalFilter,
213
preGlobalFilteredRows,
214
state: { globalFilter },
215
} = useTable(
216
{
217
columns,
218
data,
219
},
220
useFilters,
221
useGlobalFilter
222
);
223
224
return (
225
<div>
226
{/* Global Search */}
227
<div>
228
<input
229
value={globalFilter || ''}
230
onChange={(e) => setGlobalFilter(e.target.value)}
231
placeholder={`Search ${preGlobalFilteredRows.length} records...`}
232
/>
233
</div>
234
235
<table {...getTableProps()}>
236
{/* Table implementation */}
237
</table>
238
</div>
239
);
240
}
241
```
242
243
### Built-in Filter Types
244
245
React Table includes several built-in filter functions for common use cases.
246
247
```javascript { .api }
248
interface FilterTypes {
249
/** Case-insensitive text contains filter */
250
text: FilterFunction;
251
/** Case-insensitive exact text match */
252
exactText: FilterFunction;
253
/** Case-sensitive exact text match */
254
exactTextCase: FilterFunction;
255
/** Array includes value filter */
256
includes: FilterFunction;
257
/** Array includes all values filter */
258
includesAll: FilterFunction;
259
/** Array includes some values filter */
260
includesSome: FilterFunction;
261
/** Value included in array filter */
262
includesValue: FilterFunction;
263
/** Strict equality filter */
264
exact: FilterFunction;
265
/** Loose equality filter */
266
equals: FilterFunction;
267
/** Numeric range filter */
268
between: FilterFunction;
269
}
270
```
271
272
**Filter Type Examples:**
273
274
```javascript
275
const columns = [
276
{
277
Header: 'Name',
278
accessor: 'name',
279
filter: 'text', // Case-insensitive contains
280
},
281
{
282
Header: 'Status',
283
accessor: 'status',
284
filter: 'exactText', // Exact match
285
},
286
{
287
Header: 'Age',
288
accessor: 'age',
289
filter: 'between', // Numeric range
290
Filter: ({ column: { filterValue = [], setFilter } }) => (
291
<div>
292
<input
293
value={filterValue[0] || ''}
294
type="number"
295
onChange={(e) => setFilter([e.target.value, filterValue[1]])}
296
placeholder="Min"
297
/>
298
<input
299
value={filterValue[1] || ''}
300
type="number"
301
onChange={(e) => setFilter([filterValue[0], e.target.value])}
302
placeholder="Max"
303
/>
304
</div>
305
),
306
},
307
{
308
Header: 'Tags',
309
accessor: 'tags',
310
filter: 'includesSome', // Array intersection
311
},
312
];
313
```
314
315
### Custom Filter Functions
316
317
Create custom filter logic for specialized filtering needs.
318
319
```javascript { .api }
320
/**
321
* Custom filter function signature
322
* @param rows - Array of rows to filter
323
* @param columnIds - Array of column IDs being filtered
324
* @param filterValue - The filter value
325
* @returns Filtered array of rows
326
*/
327
interface CustomFilterFunction {
328
(rows: Row[], columnIds: string[], filterValue: any): Row[];
329
/** Auto-removal logic */
330
autoRemove?: (filterValue: any, column?: Column) => boolean;
331
}
332
```
333
334
**Custom Filter Examples:**
335
336
```javascript
337
// Custom filter for date ranges
338
const dateRangeFilter = (rows, columnIds, filterValue) => {
339
const [startDate, endDate] = filterValue || [];
340
341
if (!startDate && !endDate) return rows;
342
343
return rows.filter(row => {
344
return columnIds.some(columnId => {
345
const cellValue = row.values[columnId];
346
const date = new Date(cellValue);
347
348
if (startDate && date < new Date(startDate)) return false;
349
if (endDate && date > new Date(endDate)) return false;
350
351
return true;
352
});
353
});
354
};
355
356
// Auto-remove when both dates are empty
357
dateRangeFilter.autoRemove = (value) => {
358
return !value || (!value[0] && !value[1]);
359
};
360
361
// Custom filter for fuzzy matching
362
const fuzzyTextFilter = (rows, columnIds, filterValue) => {
363
const searchTerm = filterValue.toLowerCase();
364
365
return rows.filter(row => {
366
return columnIds.some(columnId => {
367
const cellValue = String(row.values[columnId]).toLowerCase();
368
369
// Simple fuzzy matching: allow 1 character difference per 4 characters
370
const maxDistance = Math.floor(searchTerm.length / 4);
371
return levenshteinDistance(cellValue, searchTerm) <= maxDistance;
372
});
373
});
374
};
375
376
fuzzyTextFilter.autoRemove = val => !val;
377
378
// Register custom filters
379
const table = useTable(
380
{
381
columns,
382
data,
383
filterTypes: {
384
dateRange: dateRangeFilter,
385
fuzzy: fuzzyTextFilter,
386
},
387
},
388
useFilters
389
);
390
```
391
392
### Column Filter Configuration
393
394
Configure filtering behavior at the column level.
395
396
```javascript { .api }
397
interface ColumnFilterConfig {
398
/** Filter type name or custom filter function */
399
filter?: string | FilterFunction;
400
/** Whether this column can be filtered */
401
disableFilters?: boolean;
402
/** Custom Filter component for UI */
403
Filter?: React.ComponentType<{
404
column: Column;
405
filterValue: any;
406
setFilter: (value: any) => void;
407
preFilteredRows: Row[];
408
}>;
409
}
410
```
411
412
**Column Filter Examples:**
413
414
```javascript
415
const columns = [
416
{
417
Header: 'Product Name',
418
accessor: 'name',
419
filter: 'text',
420
// Custom filter UI component
421
Filter: ({ column: { filterValue, setFilter, preFilteredRows } }) => {
422
const count = preFilteredRows.length;
423
return (
424
<input
425
value={filterValue || ''}
426
onChange={(e) => setFilter(e.target.value || undefined)}
427
placeholder={`Search ${count} products...`}
428
/>
429
);
430
},
431
},
432
{
433
Header: 'Category',
434
accessor: 'category',
435
filter: 'exactText',
436
// Dropdown filter
437
Filter: ({ column: { filterValue, setFilter, preFilteredRows } }) => {
438
const options = React.useMemo(() => {
439
const opts = new Set();
440
preFilteredRows.forEach(row => opts.add(row.values.category));
441
return [...opts.values()];
442
}, [preFilteredRows]);
443
444
return (
445
<select
446
value={filterValue || ''}
447
onChange={(e) => setFilter(e.target.value || undefined)}
448
>
449
<option value="">All</option>
450
{options.map(option => (
451
<option key={option} value={option}>
452
{option}
453
</option>
454
))}
455
</select>
456
);
457
},
458
},
459
{
460
Header: 'Price',
461
accessor: 'price',
462
disableFilters: true, // Disable filtering for this column
463
},
464
];
465
```
466
467
### Manual Filtering
468
469
Take control of filtering logic for server-side or custom implementations.
470
471
```javascript
472
function ManuallyFilteredTable({ columns, data }) {
473
const [filters, setFilters] = React.useState([]);
474
const [globalFilter, setGlobalFilter] = React.useState('');
475
476
// Fetch filtered data based on current filters
477
const filteredData = React.useMemo(() => {
478
return fetchFilteredData(data, filters, globalFilter);
479
}, [data, filters, globalFilter]);
480
481
const {
482
getTableProps,
483
getTableBodyProps,
484
headerGroups,
485
rows,
486
prepareRow,
487
} = useTable(
488
{
489
columns,
490
data: filteredData,
491
manualFilters: true, // Disable automatic filtering
492
manualGlobalFilter: true,
493
// Provide current filter state
494
state: {
495
filters,
496
globalFilter,
497
},
498
},
499
useFilters,
500
useGlobalFilter
501
);
502
503
return (
504
<div>
505
<input
506
value={globalFilter}
507
onChange={(e) => setGlobalFilter(e.target.value)}
508
placeholder="Global search..."
509
/>
510
511
<table {...getTableProps()}>
512
{/* Table implementation */}
513
</table>
514
</div>
515
);
516
}
517
```
518
519
## Types
520
521
```javascript { .api }
522
interface TableState {
523
/** Column filter configurations */
524
filters: Filter[];
525
/** Global filter value */
526
globalFilter: any;
527
}
528
529
interface Filter {
530
/** Column ID */
531
id: string;
532
/** Filter value */
533
value: any;
534
}
535
536
interface FilterMeta {
537
instance: TableInstance;
538
column: Column;
539
}
540
```