You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中使用TanStack Table实现表单式批量列过滤

TanStack Table 自定义表单批量过滤实现方案

以下是完整的React实现代码,包含表单过滤、批量应用规则及表格展示的全流程:

import { useState } from 'react';
import { useReactTable, createColumnHelper, getCoreRowModel, getFilteredRowModel } from '@tanstack/react-table';
import '@tanstack/react-table/style.css';

// 模拟业务数据
const mockData = [
  { id: 1, firstname: 'John', lastname: 'Doe', age: 30 },
  { id: 2, firstname: 'Jane', lastname: 'Smith', age: 25 },
  { id: 3, firstname: 'Bob', lastname: 'Johnson', age: 35 },
  { id: 4, firstname: 'Alice', lastname: 'Williams', age: 28 },
  { id: 5, firstname: 'Charlie', lastname: 'Brown', age: 22 },
];

// 列定义
const columnHelper = createColumnHelper(typeof mockData[0]);
const columns = [
  columnHelper.accessor('id', {
    header: 'ID',
    filterFn: 'includesString',
  }),
  columnHelper.accessor('firstname', {
    header: 'First Name',
    filterFn: 'includesString',
  }),
  columnHelper.accessor('lastname', {
    header: 'Last Name',
    filterFn: 'includesString',
  }),
  columnHelper.accessor('age', {
    header: 'Age',
    filterFn: 'includesString',
  }),
];

// 自定义过滤函数:不区分大小写的模糊匹配
const filterFns = {
  includesString: (row, columnId, filterValue) => {
    if (!filterValue) return true;
    return String(row.getValue(columnId)).toLowerCase().includes(filterValue.toLowerCase());
  },
};

export default function TableWithBatchFilter() {
  // 维护表单过滤输入状态
  const [formFilters, setFormFilters] = useState({
    id: '',
    firstname: '',
    lastname: '',
    age: '',
  });

  // 创建表格实例
  const table = useReactTable({
    data: mockData,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    filterFns,
    initialState: { filters: [] },
  });

  // 表单输入变更处理
  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormFilters(prev => ({ ...prev, [name]: value }));
  };

  // 应用过滤规则
  const handleApplyFilters = () => {
    // 转换为表格所需的过滤器格式,过滤空值
    const filters = Object.entries(formFilters)
      .filter(([_, value]) => value.trim() !== '')
      .map(([columnId, value]) => ({
        id: columnId,
        value,
        filterFn: 'includesString',
      }));

    table.setTableFilters(filters);
  };

  // 重置过滤规则
  const handleResetFilters = () => {
    setFormFilters({ id: '', firstname: '', lastname: '', age: '' });
    table.setTableFilters([]);
  };

  return (
    <div className="p-4">
      {/* 过滤表单 */}
      <div className="mb-4 flex gap-4 flex-wrap">
        <div className="flex flex-col gap-1">
          <label className="text-sm font-medium">ID</label>
          <input
            type="text"
            name="id"
            value={formFilters.id}
            onChange={handleInputChange}
            className="border rounded px-2 py-1 w-32"
          />
        </div>
        <div className="flex flex-col gap-1">
          <label className="text-sm font-medium">First Name</label>
          <input
            type="text"
            name="firstname"
            value={formFilters.firstname}
            onChange={handleInputChange}
            className="border rounded px-2 py-1 w-32"
          />
        </div>
        <div className="flex flex-col gap-1">
          <label className="text-sm font-medium">Last Name</label>
          <input
            type="text"
            name="lastname"
            value={formFilters.lastname}
            onChange={handleInputChange}
            className="border rounded px-2 py-1 w-32"
          />
        </div>
        <div className="flex flex-col gap-1">
          <label className="text-sm font-medium">Age</label>
          <input
            type="text"
            name="age"
            value={formFilters.age}
            onChange={handleInputChange}
            className="border rounded px-2 py-1 w-32"
          />
        </div>
        <div className="flex items-end gap-2">
          <button
            onClick={handleApplyFilters}
            className="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600 transition-colors"
          >
            应用过滤
          </button>
          <button
            onClick={handleResetFilters}
            className="bg-gray-200 px-3 py-1 rounded hover:bg-gray-300 transition-colors"
          >
            重置
          </button>
        </div>
      </div>

      {/* 表格展示 */}
      <div className="border rounded overflow-hidden">
        <table className="w-full">
          <thead>
            {table.getHeaderGroups().map(headerGroup => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map(header => (
                  <th key={header.id} className="border-b p-2 bg-gray-50 text-left">
                    {header.renderHeader()}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.map(row => (
              <tr key={row.id} className="hover:bg-gray-50">
                {row.getVisibleCells().map(cell => (
                  <td key={cell.id} className="border-b p-2">
                    {cell.renderCell()}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

关键实现说明

  1. 表单与状态绑定:通过useState维护各列的过滤输入值,确保表单输入实时同步到状态中。
  2. 过滤规则转换:点击「应用过滤」时,将表单中非空的输入值转换为TanStack Table要求的过滤器数组格式,自动忽略空值避免无效过滤。
  3. 自定义过滤逻辑:实现includesString函数完成不区分大小写的模糊匹配,可根据业务需求修改为精确匹配、范围匹配等逻辑。
  4. 表格过滤控制:使用table.setTableFilters方法批量更新过滤规则,getFilteredRowModel负责处理数据过滤后的渲染逻辑。
  5. 重置功能:一键清空表单状态并重置表格过滤器,恢复初始数据展示。

内容的提问来源于stack exchange,提问作者user2244513

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 11:55:35