Blog>
Snippets

Implementing Sorting and Filtering with Vanilla JS in React

Show how to implement custom sorting and filtering functions in Vanilla JS/TS and integrate these functionalities into a React component using TanStack Table.
import { useMemo } from 'react';
import { useTable, useSortBy } from 'react-table';

// Custom sorting function
const customSort = (rowA, rowB, columnId, desc) => {
  // Example logic for sorting strings in ascending order
  if (rowA.values[columnId].toLowerCase() > rowB.values[columnId].toLowerCase()) {
    return 1;
  }
  if (rowB.values[columnId].toLowerCase() > rowA.values[columnId].toLowerCase()) {
    return -1;
  }
  return 0;
};
This code snippet defines a custom sorting function `customSort` to sort the table data. It compares the values of two rows based on a column ID and sorts them in ascending order. You can customize this logic further based on the data type you are dealing with.
const TableComponent = ({ columns, data }) => {
  // Apply the custom sorting logic with useMemo for memoization
  const sortedData = useMemo(() => {
    const sorted = [...data].sort((a, b) => customSort(a, b, 'columnName'));
    return sorted;
  }, [data]);

  // Use the useTable and useSortBy hooks from react-table
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
  } = useTable(
    {
      columns,
      data: sortedData,
    },
    useSortBy
  );
In this snippet, we first use `useMemo` to memoize the sorted data. This optimization helps to avoid unnecessary sorts on each render. `useTable` and `useSortBy` from `react-table` are then utilized to handle table setup and provide sorting functionality respectively. The `data` is now sorted using the `customSort` function before being passed to the `useTable` hook.
return (
    <table {...getTableProps()}>
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            {headerGroup.headers.map(column => (
              <th {...column.getHeaderProps(column.getSortByToggleProps())}>{column.render('Header')}
                {column.isSorted ? (column.isSortedDesc ? ' 🔽' : ' 🔼') : ''}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map(row => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              {row.cells.map(cell => {
                return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>;
              })}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}
This snippet renders the table component. For each row and column, it renders the appropriate data cell. Additionally, it displays an icon indicating the sort direction beside the column headers that are sortable and have been sorted.