React-table global filter Regex

Viewed 460

Having trouble getting my GlobalFilter to update the table when using Regex to search for multiple results in a column.

export const Table = ({ data, columns }) => {
  const filterTypes = useMemo(
    () => ({
      // Override the default text filter to use
      // "startWith"
      text: (rows, id, filterValue) => {
        return rows.filter((row) => {
          const rowValue = row.values[id];
          const isRegexMatch = () => {
            try {
              return RegExp(filterValue).test(String(rowValue));
            } catch (err) {
              return false;
            }
          };
          return rowValue !== undefined
            ? String(rowValue)
                .toLowerCase()
                .startsWith(String(filterValue).toLowerCase()) || isRegexMatch()
            : true;
        });
      },
    }),
    []
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,
    page,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    preGlobalFilteredRows,
    setGlobalFilter,
    state,
    state: { pageIndex, pageSize },
  } = useTable(
    {
      columns,
      data,
      filterTypes,
    },
    useFilters,
    useGlobalFilter,
    useSortBy,
    usePagination
  );

  return (
    <div className="col-12">
      <div className="table-responsive mb-5">
        <GlobalFilter
          preGlobalFilteredRows={preGlobalFilteredRows}
          globalFilter={state.globalFilter}
          setGlobalFilter={setGlobalFilter}
        />
        <table {...getTableProps()} className="table">
          <thead>
            {headerGroups.map((headerGroup) => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map((column) => (
                  <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                    {column.render('Header')}
                    <span>
                      {column.isSorted ? (
                        column.isSortedDesc ? (
                          <ChevronDown baseLayer="icon" />
                        ) : (
                          <ChevronUp baseLayer="icon" />
                        )
                      ) : (
                        ''
                      )}
                    </span>
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody {...getTableBodyProps()}>
            {page.map((row, i) => {
              prepareRow(row);
              return (
                <tr {...row.getRowProps()} key={i}>
                  {row.cells.map((cell) => {
                    return (
                      <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </table>
        <div className="pagination mt-3">
          <button
            onClick={() => gotoPage(0)}
            disabled={!canPreviousPage}
            className="btn btn-sm btn-link"
          >
            {'<<'}
          </button>{' '}
          <button
            onClick={() => previousPage()}
            disabled={!canPreviousPage}
            className="btn btn-sm btn-link"
          >
            {'<'}
          </button>{' '}
          <button
            onClick={() => nextPage()}
            disabled={!canNextPage}
            className="btn btn-sm btn-link"
          >
            {'>'}
          </button>{' '}
          <button
            onClick={() => gotoPage(pageCount - 1)}
            disabled={!canNextPage}
            className="btn btn-sm btn-link"
          >
            {'>'}
          </button>{' '}
          <span className="mt-2  text-muted">
            <small>
              Page {pageIndex + 1} of {pageOptions.length}{' '}
            </small>
          </span>
          <span className="mt-2 ms-1 me-1 text-muted">
            <small> | Go to page:</small>
          </span>
          <span className="me-1">
            <input
              type="number"
              className="form-control"
              defaultValue={pageIndex + 1}
              onChange={(e) => {
                const page = e.target.value ? Number(e.target.value) - 1 : 0;
                gotoPage(page);
              }}
              style={{ width: '80px' }}
            />
          </span>
          <select
            value={pageSize}
            style={{ width: '190px' }}
            className="form-control"
            onChange={(e) => {
              setPageSize(Number(e.target.value));
            }}
          >
            {[10, 20, 30, 40, 50].map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                Show {pageSize} per page
              </option>
            ))}
            <option key={data.length} value={data.length}>
              Show All
            </option>
          </select>
        </div>
      </div>
    </div>
  );
};

I only had success so far in the console with this function being able to filter the results, but so far no luck with the react-table package.

function regexFilter(rows, ids, filterValue) {
  rows = rows.filter((row) => {
    return ids.some((id) => {
      const rowValue = row.values[id];
      const isRegexMatch = () => {
        try {
          return RegExp(filterValue).test(String(rowValue));
        } catch (err) {
          return false;
        }
      };
      return (
        String(rowValue)
          .toLowerCase()
          .includes(String(filterValue).toLowerCase()) || isRegexMatch()
      );
    });
  });
  return rows;
}

What am I not doing correctly or mis-interpreting from the documentation on filterTypes?

0 Answers
Related