Education
Developer Advocate
Last updated on Jul 3, 2024
Last updated on Jul 3, 2024
React Table is a lightweight, fast, and extendable data grid built for React applications. It is not a traditional table library, but rather a headless utility, which means it does not dictate your markup or styles, providing you with great flexibility to build a table component tailored to your needs.
One of the most powerful features of React Table is its ability to manage and apply filters to table data. React table filters allow users to narrow down the table data to only display rows that meet certain criteria, enhancing the user experience by making data more digestible.
Before diving into the world of React Table and its filtering capabilities, it's essential to set up your development environment correctly.
To get started, you'll need to create a new project if you don't have one set up already. With your new project ready, the next step is to install the React Table library. You can do this using npm or yarn:
1npm install react-table 2# or 3yarn add react-table
After installing the necessary packages, ensure that your development environment is configured to support the latest JavaScript features. This might involve setting up Babel and webpack if you're not using a boilerplate that already takes care of this for you.
React Table is a headless utility, which means you'll need to create your own table component. Let's start by defining the table columns and data.
In React Table, columns are defined as an array of objects, and table data is simply an array of objects where each object represents a row in your table.
1const columns = React.useMemo( 2 () => [ 3 { 4 Header: 'Name', 5 accessor: 'name', // accessor is the "key" in the data 6 }, 7 // Add more columns as needed 8 ], 9 [] 10); 11 12const data = React.useMemo( 13 () => [ 14 { 15 name: 'Jane Doe', 16 age: 30, 17 // Add more data as needed 18 }, 19 // Add more rows as needed 20 ], 21 [] 22);
With your columns and data defined, you can now use the useTable hook from React Table to create a table instance.
1const { 2 getTableProps, 3 getTableBodyProps, 4 headerGroups, 5 rows, 6 prepareRow, 7} = useTable({ columns, data });
Column filtering allows users to filter the data based on the content of a particular column. To add this functionality to your table component, you'll need to set up filter inputs and write filter functions.
For each column that you want to be filterable, you'll need to add a filter input. This can be done by modifying the column header to include an input field.
1// Inside your column definition 2{ 3 Header: 'Age', 4 accessor: 'age', 5 // Add a filter input 6 Filter: ({ column }) => ( 7 <input 8 value={column.filterValue || ''} 9 onChange={e => column.setFilter(e.target.value)} 10 /> 11 ), 12}
React Table allows you to write your own custom filter functions to define how the filtering should work for each column.
1// A custom filter function for age column 2function filterGreaterThan(rows, id, filterValue) { 3 return rows.filter(row => { 4 const rowValue = row.values[id]; 5 return rowValue >= filterValue; 6 }); 7} 8 9// Add the filter function to your column definition 10{ 11 Header: 'Age', 12 accessor: 'age', 13 filter: 'greaterThan', 14 Filter: // ... as above 15}
To further enhance your table, you can create and utilize your own custom filter functions for more complex filtering logic.
Each column in React Table can have a filterFn option, which allows you to define the filtering logic for that particular column.
1{ 2 Header: 'Status', 3 accessor: 'status', 4 Filter: // ... your filter input component, 5 filterFn: 'includes', 6}
You can build your own custom filter functions to handle more complex filtering requirements, such as filtering based on multiple conditions or custom data types.
1// A custom filter function that checks if the status includes a certain string 2function filterByStatus(rows, id, filterValue) { 3 return rows.filter(row => { 4 const rowValue = row.values[id]; 5 return rowValue.includes(filterValue); 6}); 7} 8 9// Add the custom filter function to your column definition 10{ 11 Header: 'Status', 12 accessor: 'status', 13 Filter: // ... your filter input component, 14 filterFn: filterByStatus, 15}
React Table provides a flexible system to manage the state of your filters, which can be controlled externally or internally within the table component.
You can control the filter state from outside the table component, which is useful for persisting filter states between sessions or syncing with URL parameters.
1const [filterInput, setFilterInput] = useState(''); 2 3// Update the state when the input changes 4const handleFilterChange = e => { 5 const value = e.target.value || undefined; 6 setFilter('name', value); // Set the filter for the 'name' column 7 setFilterInput(value); 8}; 9 10// Inside your table component 11<input 12 value={filterInput} 13 onChange={handleFilterChange} 14/>
For a more advanced use case, you might want to sync the filter state with URL parameters to allow users to share links to specific filtered views.
1// This example assumes you're using a library like React Router 2const history = useHistory(); 3const { search } = useLocation(); 4 5useEffect(() => { 6 // Parse the URL parameters 7 const params = new URLSearchParams(search); 8 const nameFilter = params.get('name') || ''; 9 10 // Set the filter state based on URL parameters 11 setFilter('name', nameFilter); 12}, [search]); 13 14// Update the URL when the filter changes 15const handleFilterChange = e => { 16 const value = e.target.value || ''; 17 setFilter('name', value); 18 19 // Update the URL 20 const params = new URLSearchParams(); 21 if (value) params.set('name', value); 22 history.push({ search: params.toString() }); 23};
In addition to column filtering, React Table supports global filtering, which allows users to search across all columns.
To implement global filtering, you'll need to add a single filter input that will control the filtering across all columns.
1const { 2 state: { globalFilter }, 3 setGlobalFilter, 4} = useTable({ columns, data }); 5 6// Your global filter input 7<input 8 value={globalFilter || ''} 9 onChange={e => setGlobalFilter(e.target.value)} 10/>
The global filtering logic can be customized to meet your specific needs, allowing you to define how the search should work across all columns.
1// A simple global filter function 2function globalFilter(rows, columns, filterValue) { 3 return rows.filter(row => { 4 return columns.some(column => { 5 const rowValue = row.values[column.id]; 6 return String(rowValue).toLowerCase().includes(String(filterValue).toLowerCase()); 7 }); 8 }); 9} 10 11// Add the global filter function to your useTable hook 12const tableInstance = useTable({ columns, data, globalFilter });
Customizing the look and feel of your filters is straightforward with React Table, as it does not impose any styling decisions on your table component.
You can apply custom styles to your filter inputs to match the design of your application. This can be done using inline styles or CSS classes.
1// Customizing the filter input with inline styles 2{ 3 Header: 'Age', 4 accessor: 'age', 5 Filter: ({ column }) => ( 6 <input 7 style={{ width: '100%', padding: '5px' }} 8 value={column.filterValue || ''} 9 onChange={e => column.setFilter(e.target.value)} 10 /> 11 ), 12}
For more control over how your data is displayed, you can create custom cell renderers. This allows you to define the markup and behavior for each cell in a column.
1// A custom cell renderer that formats the age column 2{ 3 Header: 'Age', 4 accessor: 'age', 5 Cell: ({ value }) => ( 6 <span> 7 {value} years old 8 </span> 9 ), 10}
When dealing with large datasets, performance optimization becomes crucial. React Table provides several ways to ensure that filtering remains fast and efficient.
To prevent the table from re-rendering with every keystroke, you can debounce the filter input. This means the filter will only be applied after the user has stopped typing for a specified duration.
1// Debounce the filter input 2const [filterInput, setFilterInput] = useState(''); 3 4const debouncedSetFilterInput = debounce(value => { 5setFilterInput(value); 6setGlobalFilter(value); 7}, 200); 8 9<input 10value={filterInput} 11onChange={e => debouncedSetFilterInput(e.target.value)} 12/>
For large datasets, it's important to write efficient filter functions to avoid performance bottlenecks. Optimizations can include memoizing filter functions or avoiding complex operations within the filter logic.
1// Memoizing a filter function for better performance 2const filterGreaterThan = useMemo(() => { 3 return (rows, id, filterValue) => { 4 return rows.filter(row => { 5 const rowValue = row.values[id]; 6 return rowValue >= filterValue; 7 }); 8 }; 9}, []);
Beyond basic filtering, React Table supports advanced techniques such as client-side and server-side filtering to handle different data management scenarios.
Client-side filtering is performed directly in the browser, providing instant feedback as the user types their query. This is suitable for smaller datasets that can be loaded entirely into memory.
1// Example of a client-side filter function 2const clientSideFilter = (rows, id, filterValue) => { 3 return rows.filter(row => { 4 const rowValue = row.values[id]; 5 return rowValue.toLowerCase().includes(filterValue.toLowerCase()); 6 }); 7}; 8 9// Add the client-side filter to your column definition 10{ 11 Header: 'Country', 12 accessor: 'country', 13 filter: clientSideFilter, 14}
For larger datasets, server-side filtering can be implemented to offload the filtering logic to the server, which can process the data more efficiently and return only the relevant rows to the client.
1// Example of handling server-side filtering 2const handleServerSideFilter = async filterValue => { 3 // Send the filter value to the server 4 const response = await fetch('/api/data?filter=' + encodeURIComponent(filterValue)); 5 const filteredData = await response.json(); 6 7 // Update your table data with the filtered data from the server 8 setData(filteredData); 9}; 10 11// Use the server-side filter function in your global filter input 12<input 13 value={globalFilter || ''} 14 onChange={e => handleServerSideFilter(e.target.value)} 15/>
React Table's design makes it easy to export and share filter configurations across different components or even different applications.
You can create a React component that includes predefined filters, making it reusable across your application.
1// Example of exporting a table component with predefined filters 2export default function App() { 3 const columns = useMemo(() => [ 4 // ... your column definitions 5 ], []); 6 7 const data = useMemo(() => [ 8 // ... your data 9 ], []); 10 11 const defaultColumn = useMemo(() => ({ 12 Filter: DefaultColumnFilter, 13 }), []); 14 15 const tableInstance = useTable({ columns, data, defaultColumn }); 16 17 // ... your table markup 18}
By abstracting filter configurations into their own module, you can easily import and apply the same filters across multiple table components.
1// filterConfig.js 2export const filterGreaterThan = // ... your filter function 3 4// In your table component 5import { filterGreaterThan } from './filterConfig'; 6 7// ... your column definition that uses filterGreaterThan
To illustrate the power of React Table filters, let's look at some real-world examples of how they can be applied.
An e-commerce platform can benefit greatly from React Table filters by allowing users to filter products by category, price range, rating, and more.
1// Example of a product table with multiple filters 2const columns = useMemo(() => [ 3 { 4 Header: 'Name', 5 accessor: 'name', 6 filter: 'text', 7 }, 8 { 9 Header: 'Price', 10 accessor: 'price', 11 filter: 'numeric', 12 }, 13 // ... more columns with filters 14], []);
Financial analysts can use React Table filters to sift through large datasets of financial data, such as stock prices or transaction histories, to find relevant information quickly.
1// Example of a financial data table with custom filters 2const columns = useMemo(() => [ 3 { 4 Header: 'Stock Symbol', 5 accessor: 'symbol', 6 filter: 'text', 7 }, 8 { 9 Header: 'Transaction Type', 10 accessor: 'type', 11 Filter: SelectColumnFilter, 12 filter: 'includes', 13 }, 14 // ... more columns with filters 15], []);
React Table filters are a robust feature that can significantly enhance the functionality and user experience of your data-driven applications. By understanding and implementing the various filtering techniques, you can provide users with powerful tools to navigate and manage large datasets efficiently.
• React Table is a headless utility that provides great flexibility in creating custom table components with filtering capabilities.
• Column filtering and global filtering can be implemented with custom filter functions to meet specific requirements.
• Managing filter state externally allows for persistent filters and the ability to sync with URL parameters.
• Performance optimizations, such as debouncing input and memoizing filter functions, are crucial for handling large datasets.
• React Table's design makes it easy to export and share filter configurations, promoting reusability across components.
To ensure that your React Table filters are scalable and maintainable, consider the following best practices:
• Always debounce filter inputs to improve performance and user experience.
• Use memoization to prevent unnecessary recalculations of filter functions.
• Abstract and modularize filter functions and configurations for better maintainability and reusability.
• When dealing with very large datasets, prefer server-side filtering to reduce the load on the client side.
• Keep the user interface intuitive by providing clear visual cues for active filters and easy ways to clear them.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.