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

TanStack/shadcnUI React Table列过滤功能失效求助

TanStack React Table(shadcnUI)列过滤失效问题排查与修复

问题描述

使用TanStack React Table(结合shadcnUI)开发带过滤功能的数据表格时,设置过滤条件后无预期结果返回。控制台显示过滤状态已正确设置,但表格未展示匹配的行。

相关代码

DataTable组件(data-table.tsx)

"use client";

// Define the subscription data type based on the columns created
interface TablaSubscripcionesProps {
  columns: ColumnDef<Views<"user_specific_popular_recurrent_gastos">>[];
  data: Views<"user_specific_popular_recurrent_gastos">[];
}

export function TablaSubscripciones({
  columns,
  data,
}: TablaSubscripcionesProps) {
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    onColumnFiltersChange: setColumnFilters,
    getFilteredRowModel: getFilteredRowModel(),
    state: {
      columnFilters,
    },
  });
  const { totalPrice, taxDetails, totalPriceSinImpuestos } = useSubscriptionData();
  // Convert taxDetails object to an array for easy mapping
  const taxEntries = Object.entries(taxDetails);
  // Log the current filter state
  console.log("Current filter state:", table.getState().columnFilters);
  return (
    <div className="rounded-md border">
      <Card>
        <CardHeader className=" p-4">
          <h2 className="text-lg font-bold">Subscripciones</h2>
          <p className="text-sm ">
            Administra tus subscripciones y observa el precio total.
          </p>
        </CardHeader>
        <CardContent>
          <div className="flex items-center py-4">
            <Input
              placeholder="Filter services by name"
              value={
                (table.getColumn("serviceName")?.getFilterValue() as string) ??
                ""
              }
              onChange={(event) => {
                console.log("Setting filter value to:", event.target.value); // Log the value being set

                table
                  .getColumn("serviceName")
                  ?.setFilterValue(event.target.value);
              }}
              className="max-w-sm"
            />
          </div>
          <Table>
            <TableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <TableHead key={header.id}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                    </TableHead>
                  ))}
                </TableRow>
              ))}
            </TableHeader>
            <TableBody>
              {table.getRowModel().rows.length > 0 ? (
                table.getRowModel().rows.map((row) => (
                  <TableRow key={row.id}>
                    {row.getVisibleCells().map((cell) => (
                      <TableCell key={cell.id}>
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext()
                        )}
                      </TableCell>
                    ))}
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell
                    colSpan={columns.length}
                    className="h-24 text-center"
                  >
                    No results.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </CardContent>
        <CardFooter className="flex flex-col items-start p-4 bg-gray-100 dark:bg-gray-800">
        </CardFooter>
      </Card>
    </div>
  );
}

列定义(columns.tsx)

{
  accessorKey: "serviceName",
  header: () => "Service Name",
  cell: ({ row }) => (
    <div className="font-medium">
      Netlfix{row.original.service_name}
    </div>
  ),
}

问题详情

即使在行数据的cell渲染中硬编码了"Netflix",过滤"Netflix"仍无结果返回。控制台日志显示过滤状态已正确设置:

Setting filter value to: Netflix
Current filter state: [{id: 'serviceName', value: 'Netflix'}]

问题原因与修复方案

核心问题

TanStack React Table的默认过滤逻辑是基于列的accessorKey对应的数据字段值进行匹配,当前代码存在两个关键问题:

  1. accessorKey与实际数据字段不匹配:列定义的accessorKey是serviceName,但实际数据字段是service_name(下划线命名),导致过滤逻辑找不到对应字段值。
  2. cell硬编码内容不参与过滤:默认过滤只会匹配原始数据中的service_name字段值,不会读取cell组件中硬拼接的"Netflix"字符串。

修复步骤

1. 对齐accessorKey与数据字段

将列定义的accessorKey改为与实际数据一致的service_name:

{
  accessorKey: "service_name", // 匹配数据中的字段名
  header: () => "Service Name",
  cell: ({ row }) => (
    <div className="font-medium">
      {row.original.service_name} {/* 如需硬编码可保留,但过滤逻辑默认不识别 */}
    </div>
  ),
}

2. 同步调整过滤输入框的目标列

修改输入框中获取列的代码,对应新的accessorKey:

<Input
  placeholder="Filter services by name"
  value={
    (table.getColumn("service_name")?.getFilterValue() as string) ?? ""
  }
  onChange={(event) => {
    table.getColumn("service_name")?.setFilterValue(event.target.value);
  }}
  className="max-w-sm"
/>

3. (可选)自定义过滤逻辑匹配硬编码内容

如果需要让过滤包含cell中硬拼接的"Netflix",为列添加自定义过滤函数:

{
  accessorKey: "service_name",
  header: () => "Service Name",
  cell: ({ row }) => (
    <div className="font-medium">
      Netflix{row.original.service_name}
    </div>
  ),
  filterFn: (row, columnId, filterValue) => {
    // 拼接硬编码内容与字段值,统一转为小写做模糊匹配
    const fullDisplayValue = `Netflix${row.getValue(columnId)}`.toLowerCase();
    return fullDisplayValue.includes(filterValue.toLowerCase());
  },
}

4. 验证表格状态同步

当前代码中onColumnFiltersChange与state.columnFilters的配置是正确的,确保组件在数据更新时能重新渲染表格即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:23:12