行和分页的反应表组合未按预期运行

问题描述

我正在使用react-table在表中包括行和分页,如下例所示:https://react-table.tanstack.com/docs/examples/row-selection-and-pagination。 我已经按照教程中的说明完成了示例,但是它没有按预期运行。在停止更新selectedRowsId之前,我只能选择1行。取消选择该行也不会清除它。我在做什么错了?

import React,{ useMemo,forwardRef,useRef,useEffect } from "react";
import {
  useTable,useSortBy,useFilters,useGlobalFilter,usePagination,useRowSelect
} from "react-table";
import matchSorter from "match-sorter";
import '../../static/scss/table.scss'


function DefaultColumnFilter({
  column: { filterValue,preFilteredRows,setFilter },}) {
  const count = preFilteredRows.length;

  return (
    <input
      value={filterValue || ""}
      onChange={(e) => {
        setFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
      }}
      placeholder={`Search ${count} records...`}
    />
  );
}

function SelectColumnFilter({
  column: { filterValue,setFilter,id },}) {
  // Calculate the options for filtering
  // using the preFilteredRows
  const options = React.useMemo(() => {
    const options = new Set();
    preFilteredRows.forEach((row) => {
      options.add(row.values[id]);
    });
    return [...options.values()];
  },[id,preFilteredRows]);

  // Render a multi-select Box
  return (
    <select
      value={filterValue}
      onChange={(e) => {
        setFilter(e.target.value || undefined);
      }}
    >
      <option value="">All</option>
      {options.map((option,i) => (
        <option key={i} value={option}>
          {option}
        </option>
      ))}
    </select>
  );
}

function fuzzyTextFilterFn(rows,id,filterValue) {
  return matchSorter(rows,filterValue,{ keys: [(row) => row.values[id]] });
}

fuzzyTextFilterFn.autoRemove = (val) => !val;

const IndeterminateCheckBox = forwardRef(
  ({ indeterminate,...rest },ref) => {
    const defaultRef = useRef()
    const resolvedRef = ref || defaultRef

    useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate
    },[resolvedRef,indeterminate])

    return (
      <>
        <input type="checkBox" ref={resolvedRef} {...rest} />
      </>
    )
  }
)

export default function Table({ data }) {
  console.log(data[0].title);

  const filterTypes = useMemo(
    () => ({
      // Add a new fuzzyTextFilterFn filter type.
      fuzzyText: fuzzyTextFilterFn,// Or,override the default text filter to use
      // "startWith"
      text: (rows,filterValue) => {
        return rows.filter((row) => {
          const rowValue = row.values[id];
          return rowValue !== undefined
            ? String(rowValue)
                .toLowerCase()
                .startsWith(String(filterValue).toLowerCase())
            : true;
        });
      },}),[]
  );

  const defaultColumn = useMemo(
    () => ({
      // Let's set up our default Filter UI
      Filter: DefaultColumnFilter,[]
  );

  const columns = useMemo(
    () => [
      {
        Header: "Naziv",accessor: "title",},{
        Header: "Tip",accessor: "activity_type_id",Filter: SelectColumnFilter,filter: "includes",{
        Header: "Datum",accessor: "start_time",{
        Header: "Mjesto",accessor: "location",{
        Header: "Organizator",accessor: "team_id",{
        Header: "Odgovorna osoba",accessor: "user_id",],[]
  );

  const {
    getTableProps,getTableBodyProps,headerGroups,page,prepareRow,canPrevIoUsPage,canNextPage,pageOptions,pageCount,gotoPage,nextPage,prevIoUsPage,setPageSize,selectedFlatRows,state: { pageIndex,pageSize,selectedRowIds },} = useTable(
    {
      columns,data,defaultColumn,filterTypes,initialState: { pageIndex: 0 },useRowSelect,hooks => {
      hooks.visibleColumns.push(columns => [
        // Let's make a column for selection
        {
          id: 'selection',// The header can use the table's getToggleAllRowsSelectedProps method
          // to render a checkBox
          Header: ({ getToggleAllPageRowsSelectedProps }) => (
            <div>
              <IndeterminateCheckBox {...getToggleAllPageRowsSelectedProps()} />
            </div>
          ),// The cell can use the individual row's getToggleRowSelectedProps method
          // to the render a checkBox
          Cell: ({ row }) => (
            <div>
              <IndeterminateCheckBox {...row.getToggleRowSelectedProps()} />
            </div>
          ),...columns,])
    }
  );
  return (
    <div>
      <legend className="legend">Popis aktivnosti</legend>
      <>
      <pre>
        <code>
          {JSON.stringify(
            {
              pageIndex,null,2
          )}
        </code>
      </pre>
        <table {...getTableProps()}>
          <thead>
            {
              // Loop over the header rows
              headerGroups.map((headerGroup) => (
                // Apply the header row props
                <tr {...headerGroup.getHeaderGroupProps()}>
                  {
                    // Loop over the headers in each row
                    headerGroup.headers.map((column) => (
                      // Apply the header cell props
                      <th
                        {...column.getHeaderProps(
                          column.getSortByToggleProps()
                        )}
                      >
                        {
                          // Render the header
                          column.render("Header")
                        }
                        <span>
                          {column.isSorted
                            ? column.isSortedDesc
                              ? " ?"
                              : " ?"
                            : ""}
                        </span>
                      </th>
                    ))
                  }
                  {}
                  <th>Nige</th>
                  <th>Nei</th>
                </tr>
              ))
            }
            {
              // Loop over the header rows
              headerGroups.map((headerGroup) => (
                // Apply the header row props
                <tr {...headerGroup.getHeaderGroupProps()}>
                  {
                    // Loop over the headers in each row
                    headerGroup.headers.map((column) => (
                      // Apply the header cell props
                      <th>
                        <div>
                          {column.canFilter ? column.render("Filter") : null}
                        </div>
                      </th>
                    ))
                  }
                  {}
                  <th></th>
                  <th></th>
                </tr>
              ))
            }
          </thead>
          {/* Apply the table body props */}
          <tbody {...getTableBodyProps()}>
          {page.map((row,i) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => {
                  return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                })}
              </tr>
            )
          })}
        </tbody>
        </table>
        <div className="pagination">
          <button onClick={() => gotoPage(0)} disabled={!canPrevIoUsPage}>
            {"<<"}
          </button>{" "}
          <button onClick={() => prevIoUsPage()} disabled={!canPrevIoUsPage}>
            {"<"}
          </button>{" "}
          <button onClick={() => nextPage()} disabled={!canNextPage}>
            {">"}
          </button>{" "}
          <button
            onClick={() => gotoPage(pageCount - 1)}
            disabled={!canNextPage}
          >
            {">>"}
          </button>{" "}
          <span>
            Page{" "}
            <strong>
              {pageIndex + 1} of {pageOptions.length}
            </strong>{" "}
          </span>
          <span>
            | Go to page:{" "}
            <input
              type="number"
              defaultValue={pageIndex + 1}
              onChange={(e) => {
                const page = e.target.value ? Number(e.target.value) - 1 : 0;
                gotoPage(page);
              }}
              style={{ width: "100px" }}
            />
          </span>{" "}
          <select
            value={pageSize}
            onChange={(e) => {
              setPageSize(Number(e.target.value));
            }}
          >
            {[10,20,30,40,50].map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                Show {pageSize}
              </option>
            ))}
          </select>
        </div>
        <p>Selected Rows: {Object.keys(selectedRowIds).length}</p>
      <pre>
        <code>
          {JSON.stringify(
            {
              selectedRowIds: selectedRowIds,'selectedFlatRows[].original': selectedFlatRows.map(
                d => d.original
              ),2
          )}
        </code>
      </pre>
      </>
    </div>
  );
}

解决方法

我找到了解决方案。 index.js文件的<React.StrictMode>包装了<App />。卸下<React.StrictMode>可以对其进行修复并正常运行。这可能是一个错误,应该修复。