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

如何在Tanstack React-Table全局过滤器中实现精确匹配?

在TanStack React Table中实现带精确匹配的全局过滤器

需求描述

我想在TanStack React Table的全局过滤器里实现类似谷歌搜索的逻辑——用双引号包裹关键词时触发精确匹配,比如搜索"male"时,不会返回包含female的行。我写了初步的匹配逻辑,但不知道怎么覆盖默认的全局过滤器函数,附上了可运行的全局搜索示例代码,求具体实现方法。

我的初步匹配逻辑(未测试):

function getRandomBoolean = (filter, row) => {
  const searchTerm = filter.value.trim();
  if (searchTerm.startsWith('"') && searchTerm.endsWith('"')) {
    // Perform an exact match search if the search term is enclosed in quotes
    const exactSearchTerm = searchTerm.slice(1, -1);
    return row === exactSearchTerm;
  } else {
    // Perform a regular search if no quotes are used
    return row.toLowerCase().includes(searchTerm.toLowerCase());
  }
}

实现步骤

1. 修正并完善自定义全局过滤函数

原函数存在语法错误、参数不匹配React Table规范、引号判断逻辑错误等问题,修正后的函数如下:

const customGlobalFilter = (rows, id, filterValue) => {
  const searchTerm = filterValue.trim();
  if (!searchTerm) return rows;

  // 精确匹配:处理双引号包裹的关键词
  if (searchTerm.startsWith('"') && searchTerm.endsWith('"')) {
    const exactTerm = searchTerm.slice(1, -1).toLowerCase();
    return rows.filter(row => {
      // 遍历所有单元格,存在一个精确匹配则保留该行
      return Object.values(row.values).some(cellValue => {
        // 统一转字符串处理,兼容数值类型
        return String(cellValue).toLowerCase() === exactTerm;
      });
    });
  }

  // 普通模糊匹配:大小写不敏感
  const lowerTerm = searchTerm.toLowerCase();
  return rows.filter(row => {
    return Object.values(row.values).some(cellValue => {
      return String(cellValue).toLowerCase().includes(lowerTerm);
    });
  });
};

2. 在useTable中配置自定义过滤函数

在useTable的配置对象中添加globalFilterFn属性,传入自定义函数即可覆盖默认逻辑:

const tableInstance = useTable({
  columns: columns,
  data: data,
  globalFilterFn: customGlobalFilter // 绑定自定义全局过滤函数
}, useGlobalFilter);

完整修改后的代码

import React, { useMemo } from 'react'
import { useTable, useGlobalFilter } from 'react-table'

const COLUMNS = [
    { Header: 'id', accessor: 'id' },
    { Header: 'First name', accessor: 'first_name' },
    { Header: 'Last name', accessor: 'last_name' },
    { Header: 'Mail', accessor: 'email' },
    { Header: 'gender', accessor: 'gender' },
    { Header: 'age', accessor: 'age' },
    { Header: 'country', accessor: 'country' },
    { Header: 'Phone', accessor: 'phone' }
];

const MOCK_DATA = [
    {"id":1,"first_name":"Abey","last_name":"Shattock","email":"ashattock0@who.int","gender":"male","age":60,"country":"Sweden","phone":"3235563967"},
    {"id":2,"first_name":"Gert","last_name":"Verey","email":"gverey1@miitbeian.gov.cn","gender":"male","age":39,"country":"Argentina","phone":"6617228260"},
    {"id":3,"first_name":"Elsa","last_name":"McDermott-Row","email":"gmcdermottrow2@fc2.com","gender":"female","age":73,"country":"China","phone":"5049019528"},
    {"id":4,"first_name":"Ade","last_name":"Southwick","email":"asouthwick3@gmpg.org","gender":"male","age":58,"country":"France","phone":"2562514369"},
    {"id":5,"first_name":"Angelina","last_name":"Almond","email":"aalmond4@ezinearticles.com","gender":"Female","age":30,"country":"Paraguay","phone":"9509201868"},
];

export const GlobalFilter = ({filter, setFilter}) => {
    return (
        <span>
            Search: {' '} 
            <input value={filter || ''} onChange={(e) => setFilter(e.target.value)} />
        </span>
    )
}

export const BasicTable = () => {
    const columns = useMemo(() => COLUMNS, []);
    const data = useMemo(() => MOCK_DATA, []);

    // 自定义全局过滤函数
    const customGlobalFilter = (rows, id, filterValue) => {
        const searchTerm = filterValue.trim();
        if (!searchTerm) return rows;

        // 精确匹配:双引号包裹关键词
        if (searchTerm.startsWith('"') && searchTerm.endsWith('"')) {
            const exactTerm = searchTerm.slice(1, -1).toLowerCase();
            return rows.filter(row => {
                return Object.values(row.values).some(cellValue => {
                    return String(cellValue).toLowerCase() === exactTerm;
                });
            });
        }

        // 普通模糊匹配
        const lowerTerm = searchTerm.toLowerCase();
        return rows.filter(row => {
            return Object.values(row.values).some(cellValue => {
                return String(cellValue).toLowerCase().includes(lowerTerm);
            });
        });
    };

    const tableInstance = useTable({
        columns: columns,
        data: data,
        globalFilterFn: customGlobalFilter // 覆盖默认全局过滤函数
    }, useGlobalFilter);

    const {getTableProps, getTableBodyProps, prepareRow, state, setGlobalFilter, headerGroups, rows } = tableInstance;
    const { globalFilter } = state;

    return (
        <div>
            <GlobalFilter filter={globalFilter} setFilter={setGlobalFilter}/>
            <table { ...getTableProps() }>
                <thead>
                    {headerGroups.map(headerGroup => (
                        <tr {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map(column => (
                                <th {...column.getHeaderProps()}>{column.render('Header')}</th>
                            ))}
                        </tr>
                    ))}
                </thead>
                <tbody { ...getTableBodyProps() }>
                    {rows.map(row => {
                        prepareRow(row);
                        return (
                            <tr {...row.getRowProps()}>
                                {row.cells.map(cell => (
                                    <td {...cell.getCellProps()}> {cell.render('Cell')}</td>
                                ))}
                            </tr>
                        );
                    })}
                </tbody>
            </table>
        </div>
    )
}

效果说明

  • 输入male:模糊匹配所有包含male/Female的行(大小写不敏感)
  • 输入"male":仅返回gender字段精确等于male的行(不会匹配female)
  • 输入"Female":仅返回gender字段为Female的行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:44:55