1

I'm using react-table v7.8.0 to create a table with 4 columns. I'd like the the table to be sorted by columns date and views. My problem is that the table is only being sorted by the date column.

I have some pagination and manual sorting that appears to be working as expected. I think I've followed the documentation and I'm unsure where my mistake is.

The data is configured in the following file before being passed to a table component:

ViewsPageDayTable.js:

const postDateTemplate = { year: "numeric", month: "short", day: "numeric" }

import Link from "@/components/Link"
import { useMemo } from "react"

import siteMetadata from "@/data/siteMetadata"

import Table from "@/components/homeBrewAnalytics/table"
import LocationCountItem from "@/components/homeBrewAnalytics/locationCountItem"

export default function ViewsPageDayTable({ data }) {
  const parsedData = []
  for (var i = 0; i < data.length; i++) {
    const dataRow = {}
    for (var j in data[i]) {
      if (j === "date") {
        var date = new Date(data[i][j])
        dataRow["date"] = date.toLocaleDateString(siteMetadata.locale, postDateTemplate)
      } else if (j === "page") {
        dataRow["page"] = data[i][j]
      } else if (j === "country_count") {
        var value = 0
        if (data[i][j] == null) {
          value = "unknown"
          dataRow["country_count"] = null
        } else {
          value = data[i][j]
          value = value.replaceAll("(", "[").replaceAll(")", "]").replaceAll("'", '"')
          value = JSON.parse(value)
          dataRow["country_count"] = value
        }
      } else if (j === "views") {
        dataRow["views"] = parseInt(data[i][j])
      }
    }
    parsedData.push(dataRow)
  }

  const PageCellProcessor = ({ value, row: { index }, column: { id } }) => {
    return (
      <Link href={value} className="hover:underline">
        {" "}
        {value}{" "}
      </Link>
    )
  }

  const LocationCellProcessor = ({ value }) => {
    if (value == null) return <div></div>
    const result = []
    for (var z = 0; z < value.length; z++) {
      result.push(<LocationCountItem value={value[z]} />)
    }
    return (
      <div key={value} className="flex flex-shrink">
        {result}{" "}
      </div>
    )
  }

  const columns = useMemo(
    () => [
      {
        Header: "Date",
        accessor: "date",
        sortType: (a, b) => {
          return new Date(b) - new Date(a)
        },
      },
      {
        Header: "Page",
        accessor: "page",
        Cell: PageCellProcessor,
      },
      {
        Header: "Views",
        accessor: "views",
        sortType: 'basic',
      },
      {
        Header: "Location",
        accessor: "country_count",
        Cell: LocationCellProcessor,
      },
    ],
    []
  )

  return (
    <div
      id="viewsPerPagePerDay"
      className="min-h-32 col-span-3 border-separate border-2 border-slate-800 p-3"
    >
      <Table columns={columns} data={parsedData} />
    </div>
  )
}

Table.js:

import { React, useMemo } from "react"

import { useTable, useFilters, useSortBy, usePagination } from "react-table"

import { useState } from "react"

export default function Table({ columns, data, isPaginated = true }) {
  const [filterInput, setFilterInput] = useState("")

  const handleFilterChange = (e) => {
    const value = e.target.value || undefined
    setFilter("page", value)
    setFilterInput(value)
  }

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    prepareRow,
    setFilter,
    canPreviousPage,
    canNextPage,
    pageOptions,
    nextPage,
    previousPage,
    state: { pageIndex, pageSize },
  } = useTable(
    {
      columns,
      data,
      initialState: {
        defaultCanSort: true,
        disableSortBy: false,
        manualSortBy: true,
        sortBy: useMemo(
          () => [
            {
              id: "date",
              desc: false,
            },
            {
              id: "views",
              desc: true,
            },
          ],
          []
        ),
        pageIndex: 0,
        pageSize: 15,
        manualPagination: true,
      },
    },
    useFilters,
    useSortBy,
    usePagination
  )
  return (
    <>
      <div className="flex justify-between align-middle">
        <div> Page Views</div>
        <input
          className="mr-0 rounded-sm border border-gray-700 dark:border-gray-500 "
          value={filterInput}
          onChange={handleFilterChange}
          placeholder={" Page name filter"}
        />
      </div>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th
                  {...column.getHeaderProps(column.getSortByToggleProps())}
                  className={
                    column.isSorted ? (column.isSortedDesc ? "sort-desc" : "sort-asc") : ""
                  }
                >
                  {column.render("Header")}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row, _) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                })}
              </tr>
            )
          })}
        </tbody>
      </table>
      {Boolean(isPaginated) && (
        <div id="pagination">
          <div id="pageNum">
            page {pageIndex + 1} of {pageOptions.length}
          </div>{" "}
          <div id="nextPrevButtons">
            {canPreviousPage ? (
              <div id="backButton" onClick={() => previousPage()}>
                Previous
              </div>
            ) : null}
            {canNextPage ? (
              <div id="nextButton" onClick={() => nextPage()}>
                Next{" "}
              </div>
            ) : null}
          </div>
        </div>
      )}
    </>
  )
}

John
  • 949
  • 1
  • 9
  • 20

0 Answers0