having difficulties sorting a react table

This is the complete component code snippet:

import {
  ColumnDef,
  flexRender,
  SortingState,
  useReactTable,
  getCoreRowModel,
} from "@tanstack/react-table";
import { useIntersectionObserver } from "@/hooks";
import {
  Box,
  Flex,
  Text,
  Paper,
  Table,
  Skeleton,
  BoxProps,
  useMantineTheme,
} from "@mantine/core";
import {
  forwardRef,
  ReactNode,
  useEffect,
  useState,
  useMemo,
  useRef,
  memo,
} from "react";
import { QueryFunction, useInfiniteQuery } from "@tanstack/react-query";
import { RiDatabase2Line } from "react-icons/ri";
import { css } from "@emotion/css";

export type FetchFn<T> = (props: { pageParam: number }) => Promise<T[]>;

interface TableComponentProps<T> {
  queryFn: QueryFunction<T[], string[], number>;
  columns: ColumnDef<T, any>[];
  queryKey: any[];
}

const TableComponent: <T>(props: TableComponentProps<T>) => ReactNode = memo(
  ({ queryKey, queryFn, columns }) => {
    const skullComponentRef = useRef<HTMLDivElement>(null);
    const [sortingState, setSortingState] = useState<SortingState>([]);
    const entry = useIntersectionObserver(skullComponentRef, {});
    const isVisible = !!entry?.isIntersecting;
    const { colors } = useMantineTheme();

    const {
      data,
      isLoading,
      fetchStatus,
      hasNextPage,
      isRefetching,
      fetchNextPage,
    } = useInfiniteQuery({
      queryFn,
      initialPageParam: 0,
      refetchOnWindowFocus: false,
      staleTime: 1 * 60 * 1000, // 1 min
      queryKey: [...queryKey, sortingState],
      getNextPageParam: (lastPage, allpages) =>
        lastPage.length ? allpages.length : null,
    });

    const scrollPingPong = () => {
      const tableContainer = document.querySelector<HTMLDivElement>(
        ".mantine-ScrollArea-viewport"
      );
      if (tableContainer && skullComponentRef.current) {
        tableContainer.scrollTop =
          tableContainer.scrollHeight -
          tableContainer.clientHeight -
          skullComponentRef.current.offsetHeight;
        tableContainer.scrollTop =
          tableContainer.scrollHeight - tableContainer.clientHeight;
      }
    };

    const flatData = useMemo(
      () => data?.pages?.flatMap((row) => row) ?? [],
      [data]
    );

    const table = useReactTable({
      columns,
      data: flatData,
      state: { sorting: sortingState },
      onSortingChange: setSortingState,
      getCoreRowModel: getCoreRowModel(),
    });

    useEffect(() => {
      if (isVisible && hasNextPage) {
        scrollPingPong();
        fetchNextPage();
      }
    }, [isVisible, hasNextPage, fetchNextPage]);

    return (
      <Paper
        mt="md"
        bg="white"
        withBorder
        radius={"lg"}
        style={{ overflow: "hidden" }}
      >
        <Table.ScrollContainer
          minWidth={800}
          h={`calc(100vh - 80px - 4rem)`}
          className={css({
            ".mantine-ScrollArea-viewport": { paddingBottom: 0 },
          })}
        >
          <Table
            className={css({
              "tbody tr:nth-child(even)": {
                background: colors.tailwind_gray[0],
              },
            })}
            verticalSpacing="md"
            horizontalSpacing="xl"
            withRowBorders={false}
          >
            <Table.Thead
              h="4rem"
              c="white"
              bg={colors.tailwind_indigo[6]}
              style={{ position: "sticky", top: 0, zIndex: 1 }}
            >
              {table.getHeaderGroups().map((headerGroup) => (
                <Table.Tr key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <Table.Th
                      style={{ cursor: "pointer" }}
                      key={header.id}
                      onClick={() => {
                        header.column.toggleSorting();
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      {{
                        asc: " 🔼",
                        desc: " 🔽",
                      }[header.column.getIsSorted() as string] ?? null}
                    </Table.Th>
                  ))}
                </Table.Tr>
              ))}
            </Table.Thead>
            <Table.Tbody
              style={{
                maxHeight: "calc(100vh - 134px)",
                overflowY: "auto",
              }}
              className={css({
                "& tr:hover": {
                  transition: "background .1s ease",
                  background: `${colors.tailwind_gray[1]} !important`,
                },
              })}
            >
              {table.getRowModel().rows.map((row) => (
                <Table.Tr style={{ cursor: "pointer" }} key={row.id}>
                  {row.getVisibleCells().map((cell) => (
                    <Table.Td
                      key={cell.id}
                      onClick={() => {
                        cell.column.id !== "action" && row.toggleSelected();
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </Table.Td>
                  ))}
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>

          {(hasNextPage || isRefetching || isLoading) && (
            <Skull
              skullAmount={isLoading ? 10 : 3}
              ref={skullComponentRef}
              px="xs"
            />
          )}
          {fetchStatus === "idle" && !hasNextPage && (
            <Flex
              py="lg"
              gap="xs"
              h="100%"
              align="center"
              tt="capitalize"
              justify="center"
              c="tailwind_submarine.9"
              bg="tailwind_submarine.0"
            >
              <RiDatabase2Line size={25} />
              <Text>no further records found.</Text>
            </Flex>
          )}
        </Table.ScrollContainer>
      </Paper>
    );
  }
);

const Skull = forwardRef<HTMLDivElement, BoxProps & { skullAmount: number }>(
  ({ skullAmount, ...props }, ref) => {
    return (
      <Box ref={ref} {...props}>
        {Array(skullAmount)
          .fill(null)
          .flatMap((_, key) => {
            return <Skeleton h="3.5rem" mt="xs" key={key} />;
          })}
      </Box>
    );
  }
);

export default TableComponent;

Here it's being utilized:

import {
  Menu,
  Modal,
  Flex,
  Title,
  Stack,
  Button,
  Checkbox,
  ActionIcon,
  useMantineTheme,
} from "@mantine/core";
import { useQueryClient, useMutation } from "@tanstack/react-query";
import { IRetailer } from "@/providers/onboardingformprovider";
import { RiDeleteBin6Line, RiEdit2Line } from "react-icons/ri";
import { createColumnHelper } from "@tanstack/react-table";
import { BsThreeDotsVertical } from "react-icons/bs";
import TableComponent, { FetchFn } from "./table";
import { useDisclosure } from "@mantine/hooks";
import { useState } from "react";

interface Product
  extends Pick<
    IRetailer,
    | "productname"
    | "priceperunit"
    | "productquantity"
    | "productcategory"
    | "productdescription"
  > {
  check?: any;
  action?: any;
}

const columnHelper = createColumnHelper<Product>();

const ProductsList = () => {
  const [selectedProduct, setSelectedProduct] = useState<Product>();
  const [opened, { open, close }] = useDisclosure(false);
  const [products, setProducts] = useState<Product[]>([
    ...
  ]);
  const { colors } = useMantineTheme();
  const client = useQueryClient();

  ...

  return (
    <>
      <TableComponent
        columns={columns}
        queryKey={["products"]}
        queryFn={fetchProducts}
      />
      <Modal
        ...
      >
        ...
      </Modal>
    </>
  );
};

export default ProductsList;

The sorting icons visually change their appearance based on the sorting state, but the columns are not visually sorted in ascending or descending order. The issue is related to using the "useInfiniteQuery" hook.

I have tried other examples online and the code appears to be valid.

Answer â„–1

this part was missing

  const table = useReactTable({
  columns,
  data: flatData,
  state: { sorting: sortingState, columnFilters, globalFilter },
  onSortingChange: setSortingState,
  getCoreRowModel: getCoreRowModel(),
  onColumnFiltersChange: setColumnFilters,
  onGlobalFilterChange: setGlobalFilter,
  getSortedRowModel: getSortedRowModel(),  <=========
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue: Trying to render objects as React children is invalid (object found with keys {_id}). If you intended to display multiple children, use an array instead

My intention in the NextJS application is to retrieve JSON data from my MongoDB database using getInitialProps as shown below: static async getInitialProps(ctx) { const res = await fetch('http://localhost:3000/api/endpoint'); const j ...

Stop openapi-generator from altering enum names in JavaScript/TypeScript

We have implemented the openapi generator to create our REST client and it has been quite effective. However, we encountered an issue when using enums in the format UPERCASE_UNDERSCORE, as it ended up removing the underscores which caused inconvenience. Th ...

Tips for globally overriding MUIv4 class in JSS for nested themes

Summary: Skip to EDIT2 MUIv4 has generated the following classes for me based on my nested theming: <label class="MuiFormLabel-root-121 MuiInputLabel-root-113 MuiInputLabel-formControl-115 MuiInputLabel-animated-118 MuiInputLabel-shrink-117 M ...

Guide to triggering React Material-UI modal and filling it with data from an Ajax request when a button is clicked

Despite my efforts to find a similar question, I couldn't come across one. My apologies if I overlooked it. Currently, I am working on a React Material-UI project to develop a basic web application. Within this application, there is an XGrid that disp ...

Utilizing a custom hook alongside another hook in React - a streamlined approach?

I am currently developing an app using React with next.js. There is a GraphQL query that I need to run in order to retrieve some data, but I seem to be encountering some issues. When I use the useQuery hook as shown below, it successfully returns the res ...

Capturing user input with Angular Material forms in HTML

In the process of working on a project in Angular, I am utilizing the Angular Material component library. As part of this project, I am creating a form with multiple fields. Everything is functioning properly, however, the layout appears slightly off: ht ...

The authentication loop conundrum in React Axios PUT is driving me crazy!

While authentication works fine for GET requests, I encounter an issue when trying to authenticate PUT and POST requests as it prompts for the USERNAME and PASSWORD repeatedly. I have written authentication code for both GET and PUT, but I am unable to det ...

The error message "TypeError: Trying to access properties of an undefined object (reading '800')" is being displayed

Every time I launch my application, I encounter the error message: "TypeError: Cannot read properties of undefined (reading '800')". import React, { useState } from 'react'; import { Menu, MenuItem, Avatar, Box, ThemeProvider} ...

Breaking down the initial state within a redux reducer

Can you explain the distinction between returning state in the default case of a Redux reducer using return state and return { ...state } ? ...

Assign a variable with the value returned by a function

Can you help me with this question I have about validating fields with a function using AbstractControl? errorVar: boolean = false function(c: AbstractControl): {[key: string]: string } | null { // validation if 'test' is true or not goes here ...

The console indicates that the state's arrays have been filled, yet I'm unable to retrieve the object[0]

In my code, the functions that populate the state are called on component will mount. When I log the state on the render, this is what I observe in the log. The log clearly shows that the arrays in the state have been populated, although there seems to be ...

Error in React Component: Array objects in response are not in correct order

My React app is receiving data via websocket, with a big object that contains game information. One of the properties is an array of player objects: { propertyX: "X", players: [{player1}, {player2}, {player3}], propertyY: "Y" } The issue I'm f ...

Navigational bar with React and Next.js. Issue: Hydration unsuccessful due to inconsistencies between the initial UI and the server-rendered content

I am working on a project with Next.js and React. I've created a navbar component but I keep encountering the following error message multiple times: Error: Hydration failed because the initial UI does not match what was rendered on the server. Warni ...

Definition of a Typescript Global.d.ts module for a function that is nested within another function

Simply put, I have a npm module that exports a function along with another function attached to it: // @mycompany/module ... const someTool = (options) => { // do some cool stuff }; someTool.canUseFeature1 = () => { return canUseSomeFeature1(); ...

What is the process for passing a component as a parameter to a function within a different component?

Within my scenario, I have a series of components '1,2,3,...' imported into another primary component 'A'. Within component 'A', certain operations are performed and a filtered component is then returned from the list of compo ...

Tips for rearranging objects within a jsPDF document to prevent vertical overlap when a table grows in size

I am new to React and Javascript. I have been struggling to find a solution to my issue while trying to create a .pdf document for a customer invoice using "jsPdf" along with its plugin "jspdf-autoTable". So far, everything is being generated correctly by ...

Exploring the archives of PubNub within Angular5

I've been working on integrating PubNub history into my web app, but I'm currently only able to view it in the console. Here's what I have so far: pubnub.history( { channel: 'jChannel', reverse: false, ...

The call in TypeScript React does not match any overload

Encountering an error with a React component that I wrote and seeking assistance. The primary component code snippet: export interface ICode { code: (code: string) => void; } export default class UserCode extends React.Component{ state = { formFil ...

Exploring the power of TypeScript strictNullChecks with array manipulation

My understanding of Typescript's behavior with the compiler option strictNullChecks enabled is not yet complete. It appears that in some cases, Typescript (version 2.4.1) recognizes an item in a string[] as a string, while other times it does not: in ...

TypeScript Definitions for Material-UI version 15

Is there a Material-UI v15 TypeScript definition file in the works? I need it for a project I'm working on and as a TypeScript newbie, I want to make sure the custom file I've begun is accurate. ...