【问题标题】:Global Filter in react-table v8 isn't workingreact-table v8 中的全局过滤器不起作用
【发布时间】:2022-08-18 17:43:20
【问题描述】:

我对 react-table v8 过滤器进行了稍微修改的实现:https://tanstack.com/table/v8/docs/examples/react/filters

在原版中,他们似乎使用自定义过滤器函数来全局过滤表,但它需要另一个我不想包含的库,文档对此不是很清楚,但似乎有内置函数我可以使用:https://tanstack.com/table/v8/docs/api/features/filters

但是,一旦更改表格,表格就会停止过滤,我尝试不包括globalFilterFn,并将其设置为globalFilterFn: \"includesString\",这是我提到的内置功能之一,但到目前为止没有任何效果。

这是我的代码:

import React from \"react\";
import ReactDOM from \"react-dom/client\";

import \"./index.css\";

import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  FilterFn,
  ColumnDef,
  flexRender
} from \"@tanstack/react-table\";

//import { RankingInfo, rankItem } from \"@tanstack/match-sorter-utils\";

import { makeData, Person } from \"./makeData\";

/* declare module \"@tanstack/table-core\" {
  interface FilterMeta {
    itemRank: RankingInfo;
  }
}

const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
  // Rank the item
  const itemRank = rankItem(row.getValue(columnId), value);

  // Store the itemRank info
  addMeta({
    itemRank
  });

  // Return if the item should be filtered in/out
  return itemRank.passed;
}; */

function App() {
  const rerender = React.useReducer(() => ({}), {})[1];

  const [globalFilter, setGlobalFilter] = React.useState(\"\");

  const columns = React.useMemo<ColumnDef<Person>[]>(
    () => [
      {
        header: \"Name\",
        footer: (props) => props.column.id,
        columns: [
          {
            accessorKey: \"firstName\",
            cell: (info) => info.getValue(),
            footer: (props) => props.column.id
          },
          {
            accessorFn: (row) => row.lastName,
            id: \"lastName\",
            cell: (info) => info.getValue(),
            header: () => <span>Last Name</span>,
            footer: (props) => props.column.id
          },
          {
            accessorFn: (row) => `${row.firstName} ${row.lastName}`,
            id: \"fullName\",
            header: \"Full Name\",
            cell: (info) => info.getValue(),
            footer: (props) => props.column.id
          }
        ]
      },
      {
        header: \"Info\",
        footer: (props) => props.column.id,
        columns: [
          {
            accessorKey: \"age\",
            header: () => \"Age\",
            footer: (props) => props.column.id
          },
          {
            header: \"More Info\",
            columns: [
              {
                accessorKey: \"visits\",
                header: () => <span>Visits</span>,
                footer: (props) => props.column.id
              },
              {
                accessorKey: \"status\",
                header: \"Status\",
                footer: (props) => props.column.id
              },
              {
                accessorKey: \"progress\",
                header: \"Profile Progress\",
                footer: (props) => props.column.id
              }
            ]
          }
        ]
      }
    ],
    []
  );

  const [data, setData] = React.useState(() => makeData(500));
  const refreshData = () => setData((old) => makeData(500));

  const table = useReactTable({
    data,
    columns,
    state: {
      globalFilter
    },
    onGlobalFilterChange: setGlobalFilter,
    //globalFilterFn: \"includesString\",
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel()
  });

  return (
    <div className=\"p-2\">
      <div>
        <input
          value={globalFilter ?? \"\"}
          onChange={(event) => setGlobalFilter(event.target.value)}
          className=\"p-2 font-lg shadow border border-block\"
          placeholder=\"Search all columns...\"
        />
      </div>
      <div className=\"h-2\" />
      <table>
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => {
                return (
                  <th key={header.id} colSpan={header.colSpan}>
                    {header.isPlaceholder ? null : (
                      <>
                        <div
                          {...{
                            className: header.column.getCanSort()
                              ? \"cursor-pointer select-none\"
                              : \"\",
                            onClick: header.column.getToggleSortingHandler()
                          }}
                        >
                          {flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                          {{
                            asc: \" ????\",
                            desc: \" ????\"
                          }[header.column.getIsSorted() as string] ?? null}
                        </div>
                      </>
                    )}
                  </th>
                );
              })}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => {
            return (
              <tr key={row.id}>
                {row.getVisibleCells().map((cell) => {
                  return (
                    <td key={cell.id}>
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
      <div className=\"h-2\" />
      <div className=\"flex items-center gap-2\">
        <button
          className=\"border rounded p-1\"
          onClick={() => table.setPageIndex(0)}
          disabled={!table.getCanPreviousPage()}
        >
          {\"<<\"}
        </button>
        <button
          className=\"border rounded p-1\"
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
        >
          {\"<\"}
        </button>
        <button
          className=\"border rounded p-1\"
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
        >
          {\">\"}
        </button>
        <button
          className=\"border rounded p-1\"
          onClick={() => table.setPageIndex(table.getPageCount() - 1)}
          disabled={!table.getCanNextPage()}
        >
          {\">>\"}
        </button>
        <span className=\"flex items-center gap-1\">
          <div>Page</div>
          <strong>
            {table.getState().pagination.pageIndex + 1} of{\" \"}
            {table.getPageCount()}
          </strong>
        </span>
        <span className=\"flex items-center gap-1\">
          | Go to page:
          <input
            type=\"number\"
            defaultValue={table.getState().pagination.pageIndex + 1}
            onChange={(e) => {
              const page = e.target.value ? Number(e.target.value) - 1 : 0;
              table.setPageIndex(page);
            }}
            className=\"border p-1 rounded w-16\"
          />
        </span>
        <select
          value={table.getState().pagination.pageSize}
          onChange={(e) => {
            table.setPageSize(Number(e.target.value));
          }}
        >
          {[10, 20, 30, 40, 50].map((pageSize) => (
            <option key={pageSize} value={pageSize}>
              Show {pageSize}
            </option>
          ))}
        </select>
      </div>
      <div>{table.getPrePaginationRowModel().rows.length} Rows</div>
      <div>
        <button onClick={() => rerender()}>Force Rerender</button>
      </div>
      <div>
        <button onClick={() => refreshData()}>Refresh Data</button>
      </div>
      <pre>{JSON.stringify(table.getState(), null, 2)}</pre>
    </div>
  );
}

const rootElement = document.getElementById(\"root\");
if (!rootElement) throw new Error(\"Failed to find the root element\");

ReactDOM.createRoot(rootElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

CodeSanbox 的链接:https://codesandbox.io/s/long-monad-652jcm?file=/src/main.tsx

我在 React 方面仍然非常缺乏经验,甚至在打字稿方面更缺乏经验,所以也许我遗漏了一些明显的东西。

我是否误解了文档,也许自定义功能是必要的?

    标签: reactjs react-table


    【解决方案1】:

    您的 globalFilter 不做任何事情,您需要测试表的内容是否等于过滤器。

    【讨论】:

    • 是的,这就是问题所在,在原始示例中,使用自定义函数来过滤表,我打算使用内置函数,因为自定义函数有一个我不想要的库,但是当我改变它时过滤器停止工作
    【解决方案2】:

    当前有一个issue on GitHub,如果您的一列正在使用数字字段,则您不能使用全局过滤器。您可以通过用数据中的字符串替换数字来简单地解决它。 (.toString(),排序仍然有效)。如果之后对我来说工作得很好。 :)

    【讨论】:

      猜你喜欢
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 2016-08-19
      相关资源
      最近更新 更多