How to make tables filterable in React
Filterable tables enable users to quickly find relevant data in large datasets, improving usability in data-intensive applications. As the creator of CoreUI, a widely used open-source UI library, I’ve built filterable tables for enterprise dashboards throughout my 11 years of frontend development. The most straightforward approach is using useState to manage filter input and filtering the data array before rendering. This method provides real-time filtering with minimal code and excellent performance for typical datasets.
Use controlled input for filter text and filter data array based on whether values include the filter text.
import { useState } from 'react'
const FilterableTable = ({ data }) => {
const [filter, setFilter] = useState('')
const filteredData = data.filter(user => {
const searchText = filter.toLowerCase()
return (
user.name.toLowerCase().includes(searchText) ||
user.email.toLowerCase().includes(searchText) ||
user.role.toLowerCase().includes(searchText)
)
})
return (
<div>
<input
type='text'
placeholder='Filter by name, email, or role...'
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
{filteredData.length > 0 ? (
filteredData.map(user => (
<tr key={user.id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.role}</td>
</tr>
))
) : (
<tr>
<td colSpan='3'>No results found</td>
</tr>
)}
</tbody>
</table>
<p>{filteredData.length} of {data.length} results</p>
</div>
)
}
Here the filter state stores the current search text from the input field. The filteredData uses the array filter method to check if any column value includes the search text using case-insensitive comparison with toLowerCase(). The controlled input updates filter state on every keystroke, triggering automatic re-filtering. The empty state shows a “No results found” message when the filter yields no matches. The result count provides feedback showing how many rows match the current filter.
Best Practice Note:
This is the filtering pattern we use in CoreUI table components for responsive search functionality in enterprise applications. Add debouncing to the filter input for large datasets to improve performance, implement column-specific filters with dropdown selects for precise filtering, and combine filtering with sorting and pagination for complete table functionality.



