如何使用TanStack Table v8实现字符串日期的范围过滤及输入框绑定
日期范围筛选器绑定与字符串日期过滤方案
一、绑定日期范围输入框
用React的useState管理开始和结束日期的状态,把两个原生日期输入框和状态做双向绑定,再将日期范围传给表格的过滤逻辑。示例代码如下:
import { useState } from 'react'; import { useReactTable, ColumnDef } from '@tanstack/react-table'; // 定义数据类型 type VTDATA = { date: string; value: string }; // 接口返回数据 const abc: VTDATA[] = [ { date: '2023-12-8', value: 'mop' }, { date: '2023-10-8', value: 'qrs' }, ]; // 列配置 export const columns: ColumnDef<VTDATA>[] = [ { accessorKey: "value", header: "Value" }, { accessorKey: "date", header: "Date" }, ]; export function DateFilterTable() { // 存储日期范围状态 const [dateRange, setDateRange] = useState({ start: '', end: '' }); // 创建表格实例,集成日期过滤 const table = useReactTable({ data: abc, columns, // 全局过滤函数处理日期范围 globalFilterFn: (row, _, filterValue) => { const { start, end } = filterValue as typeof dateRange; if (!start && !end) return true; // 直接用字符串比较(YYYY-MM-DD格式支持字典序对比) const matchesStart = !start || row.getValue('date') >= start; const matchesEnd = !end || row.getValue('date') <= end; return matchesStart && matchesEnd; }, globalFilter: dateRange, }); return ( <div> {/* 日期输入框绑定 */} <input type="date" value={dateRange.start} onChange={e => setDateRange(prev => ({ ...prev, start: e.target.value }))} /> <span>至</span> <input type="date" value={dateRange.end} onChange={e => setDateRange(prev => ({ ...prev, end: e.target.value }))} /> {/* 表格渲染 */} <table> <thead> {table.getHeaderGroups().map(headerGroup => ( <tr key={headerGroup.id}> {headerGroup.headers.map(header => ( <th key={header.id}>{header.renderHeader()}</th> ))} </tr> ))} </thead> <tbody> {table.getRowModel().rows.map(row => ( <tr key={row.id}> {row.getVisibleCells().map(cell => ( <td key={cell.id}>{cell.renderCell()}</td> ))} </tr> ))} </tbody> </table> </div> ); }
二、字符串格式日期的过滤处理
API返回的YYYY-MM-DD格式字符串有个天然优势:字典序和日期时间顺序完全一致,所以有两种过滤思路:
1. 直接字符串对比(推荐)
不用转换为Date对象,直接对比字符串,性能更高还能避免时区问题:
const filterDateRange = (rowDate: string, start: string, end: string) => { if (!start && !end) return true; if (start && rowDate < start) return false; if (end && rowDate > end) return false; return true; };
注意:确保输入框的日期格式和API返回一致(原生type="date"的value就是YYYY-MM-DD,刚好匹配)。
2. 转换为Date对象对比
如果日期格式不统一(比如存在MM/DD/YYYY),或者需要处理时间部分,就转成Date对象:
const filterDateRange = (rowDate: string, start: string, end: string) => { const rowDateTime = new Date(rowDate); const startDateTime = start ? new Date(start) : new Date(-8640000000000000); // 极小时间值 const endDateTime = end ? new Date(end) : new Date(8640000000000000); // 极大时间值 // 处理无效日期(比如字符串格式错误) if (isNaN(rowDateTime.getTime())) return false; return rowDateTime >= startDateTime && rowDateTime <= endDateTime; };
三、日期范围过滤的最佳方案
- 优先用字符串直接对比:对于
YYYY-MM-DD、YYYY-MM-DD HH:mm:ss这类标准格式,字符串对比性能更好,无时区问题。 - 封装可复用过滤函数:把日期过滤逻辑抽成独立函数,方便在多个组件中复用,避免重复代码。
- 结合表格库原生过滤机制:比如给日期列单独配置
filterFn,比全局过滤更清晰,维护起来更方便。 - 处理边界情况:
- 当开始日期大于结束日期时,自动交换两者;
- 输入为空时,不对该边界做限制;
- 校验日期格式,过滤无效日期的行。
内容的提问来源于stack exchange,提问作者Bishal Khatri
相关产品推荐
相关产品推荐

