In this guide, I want to share my learnings and help you be productive in adding column filters to your data tables, and pagination which shows the filtered results count, page number etc., using React Table library (specifically V7). For more details on V7, you can check the docs snapshot.

This is a follow up post of article on creating custom react table components. So, please check it out first before going through this, as this post assumes you had the table setup done following previous article.

Step 1

Import the related filters and pagination hooks from react-table.

import { useFilters, usePagination } from "react-table"; // extra hooks that need to be imported

Step 2

Now we pass that to our table hook, and capture the state related to filters and pagination indicated below.

const {
  rows,
  page,
  pageCount,
  gotoPage,
  state: { globalFilter, pageIndex, pageSize },
  setFilter,
} = useTable(
  {
    columns,
    data,
    initialState: { pageIndex: 0, pageSize: 10 },
  },
  useFilters,
  usePagination
);

Step 3

Now instead of depending on the rows, we will be using page to iterate over the visible rows data, as we will be showing page by page.

return (
  <table>
    <thead>
      {headerGroups.map((headerGroup) => (
        <tr>
          {headerGroup.headers.map((column) => (
            <th>{column.render("Header")}</th>
          ))}
        </tr>
      ))}
    </thead>
    <tbody>
      {page.map((row) => {
        prepareRow(row);
        return (
          <tr>
            {row.cells.map((cell) => (
              <td>{cell.render("Cell")}</td>
            ))}
          </tr>
        );
      })}
    </tbody>
  </table>
);

Adding Column Filters

Lets say you have data having some kind of attribute using which you want to filter out the data. For example, our data has firstname, lastname. Now lets add role also like below.

{
  firstname: "Tony",
  lastname: "Stark",
  role: "superhero"
},
{
  firstname: "Robert",
  lastname: "Downey",
  role: "actor"
}

Imagine this experience - the user will be shown a dropdown where they can select one of the available roles from the data, and all the data gets filtered accordingly. To do this, first extract unique values for the role attribute, and pass it to dropdown. Whenever user selects any value from the dropdown, we need to trigger setFilter with that value for that particular column. React-table will take care of filtering the data using the value we selected for the column. You can build this behavior using snippet below:

// Assuming we have 3 columns (First Name, Last Name, Role). This filter is on Role related data.
const ColumnFilter = ({ columnUniqueVals, setFilter }) => {
  const [selectedVal, setSelectedVal] = useState("");

  const handleStatusChange = (evt) => {
    setFilter("role", evt.target.value || undefined);
    setSelectedVal(evt.target.value || "");
  };

  useEffect(() => {
    setFilter("role", undefined);
    setSelectedVal("");
  }, [columnUniqueVals, setFilter, setSelectedVal]);

  return (
    <Dropdown onChange={handleStatusChange} value={selectedVal}>
      <Option value="">All</Option>
      {columnUniqueVals.map((val) => (
        <Option value={val}>{val}</Option>
      ))}
    </Dropdown>
  );
};

Adding Pagination

Now we have details about the page, pageSize, overall rows due to filtering etc. Lets imagine you have a pagination component that can render these details. All we need to do is pass this data updates from our table component to your pagination component as below. Here you can see gotoPage method which can wired to click to any particular page. The total number of filtered items can be known from the value of rows.

return (
  <Table>...</Table>     // all the table related rendering
  <Pagination
    activePage={pageIndex}
    totalPages={pageCount}
    onPageChange={gotoPage}
  >
  <Pagination.Summary itemsPerPage={pageSize} totalItems={rows.length} />
</Pagination>
)

I have avoided using boilerplate code like adding keys, aria labels etc., to focus on the topic. Hope this helped in understanding how you can add filtering and pagination to your custom data tables that use React-Table library.

Follow for more!