Filtering
Built-in per-column filter popups with operator selection, two-condition AND/OR logic, and support for text, number, and date column types.
Column filters — text, number, and date
Click the filter icon in any column header. Pick an operator, enter a value, then click Apply. Try salary ≥ 130000, or filter hired Before 2021-01-01.
import DataTable, { type TableColumn } from 'react-data-table-component';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
hired: string;
}
const data: Employee[] = [
{ id: 1, name: 'Aria Chen', department: 'Engineering', salary: 155000, hired: '2019-03-12' },
{ id: 2, name: 'Marcus Webb', department: 'Product', salary: 132000, hired: '2020-07-01' },
{ id: 3, name: 'Priya Kapoor', department: 'Design', salary: 118000, hired: '2021-01-15' },
{ id: 4, name: 'Jordan Ellis', department: 'Analytics', salary: 143000, hired: '2018-11-30' },
{ id: 5, name: 'Sam Rivera', department: 'Engineering', salary: 128000, hired: '2022-04-22' },
{ id: 6, name: 'Taylor Brooks', department: 'Sales', salary: 97000, hired: '2023-02-08' },
{ id: 7, name: 'Morgan Lee', department: 'Engineering', salary: 162000, hired: '2017-09-05' },
{ id: 8, name: 'Casey Park', department: 'Design', salary: 109000, hired: '2022-11-19' },
{ id: 9, name: 'Drew Santos', department: 'Product', salary: 138000, hired: '2020-03-30' },
{ id: 10, name: 'Avery Johnson', department: 'Sales', salary: 104000, hired: '2021-08-14' },
];
const columns: TableColumn<Employee>[] = [
{ id: 'name', name: 'Name', selector: r => r.name, sortable: true, filterable: true },
{ id: 'dept', name: 'Department', selector: r => r.department, filterable: true },
{
id: 'salary',
name: 'Salary',
selector: r => r.salary,
format: r => `$${r.salary.toLocaleString()}`,
right: true,
sortable: true,
filterable: true,
filterType: 'number',
},
{ id: 'hired', name: 'Hired', selector: r => r.hired, sortable: true, filterable: true, filterType: 'date' },
];
export default function App() {
return <DataTable columns={columns} data={data} highlightOnHover pagination paginationPerPage={10} />;
}Filtering runs on the full dataset before pagination, so a filter matches rows on every page, not just the one you are viewing. The result count and page navigation update to the filtered set. This applies to client-side pagination; see theserver-side recipe for the server case.
Quick start
Add filterable: true and a stable id to any column. A filter icon appears in the column header. Filters across columns combine with AND. A row must pass every active filter to appear.
const columns: TableColumn<Row>[] = [{ id: 'name', name: 'Name', selector: r => r.name, filterable: true }];
<DataTable columns={columns} data={data} />;Filter types
Set filterType to get the right operator set and input widget. Defaults to "text".
const columns: TableColumn<Row>[] = [
{ id: 'name', name: 'Name', selector: r => r.name, filterable: true },
{ id: 'score', name: 'Score', selector: r => r.score, filterable: true, filterType: 'number' },
{ id: 'dob', name: 'Birth date', selector: r => r.dob, filterable: true, filterType: 'date' },
{ id: 'seen', name: 'Last seen', selector: r => r.seen, filterable: true, filterType: 'datetime' },
{ id: 'ranAt', name: 'Ran at', selector: r => r.ranAt, filterable: true, filterType: 'time' },
];filterType | Default operator | Input | Operators |
|---|---|---|---|
"text" (default) | Contains | Text | Contains, Does not contain, Equals, Does not equal, Begins with, Ends with, Blank, Not blank |
"number" | Equals | Number | Equals, Does not equal, Greater than, ≥, Less than, ≤, Between, Blank, Not blank |
"date" | Equals | Date | Equals, Before, After, Between, Blank, Not blank |
"datetime" | Equals | Date & time | Equals, Before, After, Between, Blank, Not blank |
"time" | Equals | Time | Equals, Before, After, Between, Blank, Not blank |
Blank / Not blank match on empty cells and need no value input.Between (number, date, datetime, and time) shows two value inputs for inclusive bounds. For "date" and "datetime" columns, selector should return an ISO string ("2024-03-15" or "2024-03-15T14:30") or any value parseable by new Date().
"date" compares by calendar day, so Equals matches any time on that day."datetime" compares the exact instant, so Equals matches a specific minute. Becausedatetime-local inputs are timezone-naive, filtering is exact only when your cell values are also local time (no Z / offset); otherwise supply a filterFunction.
"time" compares the time of day and ignores the date, so it filters across every date at once — useful for logs (“anything after 17:00”, “errors between 02:00 and 04:00”). The input accepts seconds, and the cell value may be a bare time ("17:30") or any timestamp whose time portion is read ("2024-03-15T17:30:45"). A Between whose start is later than its end wraps past midnight, so 22:00–06:00 matches an overnight window.
Time-of-day filter
Log rows across several days. Open the Time filter, choose Between, and enter 02:00 and 04:00 to surface the nightly cron failures regardless of date. Try 22:00 to 06:00 for an overnight window that wraps past midnight.
const columns: TableColumn<LogEntry>[] = [
{
id: 'at',
name: 'Time',
selector: r => r.at, // full ISO timestamp
format: r => r.at.slice(11), // show just the time
filterable: true,
filterType: 'time', // filters by time of day, ignoring the date
},
// ...
];Two conditions per column
Each filter popup has a + Add condition link. Adding a second condition reveals an AND / OR toggle. AND means both conditions must match; OR means either must match.
import type { FilterState } from 'react-data-table-component';
// The shape of one column's filter state
const filter: FilterState = {
condition1: { operator: 'startsWith', value: 'J' },
condition2: { operator: 'endsWith', value: 'son' },
logic: 'AND', // 'AND' | 'OR' — defaults to 'AND'
};Apply / Clear behaviour
Filters apply only when the user clicks Apply. Typing does not immediately re-filter. This avoids jarring mid-keystroke changes on large datasets. Clicking Clear resets the column's filter and applies immediately.
Custom filter function
Override built-in operator logic per column with filterFunction. It receives the full FilterState so both conditions are available:
import type { TableColumn, FilterState } from 'react-data-table-component';
const columns: TableColumn<Row>[] = [
{
id: 'tags',
name: 'Tags',
selector: r => r.tags.join(', '),
filterable: true,
filterFunction: (row, filter) => {
const term = (filter.condition1.value ?? '').toLowerCase();
return row.tags.some(tag => tag.toLowerCase().includes(term));
},
},
];Controlled mode
Pass filterValues and onFilterChange to own the filter state yourself. Useful for persisting it in a URL or resetting it programmatically.onFilterChange fires on every Apply or Clear click.
import { useState } from 'react';
import DataTable, { type FilterState } from 'react-data-table-component';
function App() {
const [filterValues, setFilterValues] = useState<Record<string | number, FilterState>>({});
const [resetPage, setResetPage] = useState(false);
function handleFilterChange(columnId: string | number, filter: FilterState) {
setFilterValues(prev => ({ ...prev, [columnId]: filter }));
setResetPage(v => !v); // jump back to page 1 after each filter
}
return (
<DataTable
columns={columns}
data={data}
filterValues={filterValues}
onFilterChange={handleFilterChange}
pagination
paginationResetDefaultPage={resetPage}
/>
);
}Utility exports
import { emptyFilterState, isFilterActive, type FilterState } from 'react-data-table-component';
// Create a default-empty FilterState for a given type
emptyFilterState('number'); // { condition1: { operator: 'equals' } }
emptyFilterState('text'); // { condition1: { operator: 'contains' } }
// Check whether a FilterState is actually filtering anything
isFilterActive({ condition1: { operator: 'contains' } }); // false — no value
isFilterActive({ condition1: { operator: 'contains', value: 'a' } }); // true
isFilterActive({ condition1: { operator: 'blank' } }); // true — no value neededLocalization
Use the localization prop to swap every string in the table UI. Import a pre-built locale or build your own — all keys are optional and fall back to English defaults.
// Drop-in locale
import DataTable from 'react-data-table-component';
import { fr } from 'react-data-table-component/locales';
<DataTable columns={columns} data={data} localization={fr} />;// Custom / partial override — spread a locale and replace only what you need
import { fr } from 'react-data-table-component/locales';
import type { Localization } from 'react-data-table-component';
const myLocale: Localization = {
...fr,
filter: {
...fr.filter,
applyLabel: 'Valider', // override one key
},
};
<DataTable columns={columns} data={data} localization={myLocale} />;// Built from scratch — every key is optional
import type { Localization } from 'react-data-table-component';
const custom: Localization = {
filter: {
clearLabel: 'Reset',
applyLabel: 'Go',
operators: { contains: 'has', equals: 'is' },
},
};
<DataTable columns={columns} data={data} localization={custom} />;Headless usage
Use useColumnFilter directly when building a custom table with the headless hooks. See Headless hooks for the full API.
import { useColumnFilter, type FilterState } from 'react-data-table-component';
const { filterValues, handleFilterChange, filteredData } = useColumnFilter(columns);
// Call handleFilterChange when the user applies a filter in your custom UI
function onApply(columnId: string | number, filter: FilterState) {
handleFilterChange(columnId, filter);
}
// Apply all active filters before rendering rows
const rows = filteredData(tableRows);See it combined with other features in the Server-side sort, page & filter recipe and URL-synced table state.
Prop reference
| Prop | Type | Default | Description |
|---|---|---|---|
filterValues | Record<string | number, FilterState> | - | Controlled filter state. Omit to use internal state. See Filtering. |
onFilterChange | (columnId, filter: FilterState) => void | - | Called when the user clicks Apply or Clear in a filter popup. |
Per-column filtering is configured on each TableColumnvia filterable, filterType, and filterFunction.