UseQuery API request for data for Tanstack Table not working - The request won't run, but runs without table initialization

1.1k views Asked by At

Code and Console Logs provided :)

I am trying to fetch data using React Query and Axios, and use it to initialize my Tanstack Table. The table works just fine with mock data, and the request works fine as long as the data isn't used to initialize the table. The data seems to not have loaded yet before the initialization, even though I use async/await. In fact, the data never even loads when I use it for table initialization, and the request isn't even sent (I know it from my backend console log - for backend I use Spring Boot with Spring Security).

The following is my code where all the action happens:

import { useReactTable, flexRender, getCoreRowModel } from '@tanstack/react-table';
import { useMemo } from 'react';
import { useQuery } from "@tanstack/react-query";
import { Axios } from "axios";

export const Employees = (props) => {

    console.log("render");

    const columns = useMemo(() => [
        {
            accessorKey: 'employeeId',
            header: 'ID',
            footer: 'ID'
        },
        {
            accessorKey: 'employeeName',
            header: 'Name',
            footer: 'Name'
        },
        {
            accessorKey: 'employeeDescription',
            header: 'Description',
            footer: 'Description'
        }
    ], [])

    const { data } = useQuery({
        queryKey: ["employees"], 
        queryFn: async () => {
            const result = await Axios.get(
                props.path+"/api/employees", 
                {
                    'headers': {
                        'Authorization': localStorage.getItem("token")
                    }
                }
            );
            console.log("inside");
            return result.data;
        }
    });

    console.log(data);

    const table = useReactTable({
        columns,
        data,
        getCoreRowModel: getCoreRowModel()
    })

    return (
        <>
            <table>
                <thead>
                    {table.getHeaderGroups().map(headerGroup => (
                        <tr key={headerGroup.id}>
                            {headerGroup.headers.map(header => (
                                <th key={header.id}>
                                    {flexRender(
                                        header.column.columnDef.header,
                                        header.getContext()
                                    )}
                                </th>
                            ))}
                           
                        </tr>
                    ))}
                </thead>
                <tbody>
                    {table.getRowModel().rows.map(row => (
                        <tr key={row.id}>
                            {row.getVisibleCells().map(cell => (
                                <td key={cell.id}>
                                    {
                                        flexRender(cell.column.columnDef.cell,
                                            cell.getContext())
                                    }
                                </td>
                            ))}
                        </tr>
                    ))}
                </tbody>
                
            </table>
        </> 
    );
    
}

The following is what my console returns:

all the errors are here, as well as the logs

As you can see from the logs, the component is rendered 4? times (It is the same with and without Strict Mode), and also the data stays undefined until the end. Why does the component render 4 times? Also the log from inside the request is never triggered. Why doesn't the async/await work?

I've tried fetching the data in the parent component, but it still doesn't await properly. I've tested both the Table and the useQuery Request and both work flawlessly, but when I **combine **both, it just doesn't work. Thanks for help :)

1

There are 1 answers

0
Marko Sladojevic On

I've fixed it guys, with help from the r/reactjs community from Reddit. Here are their answers: https://www.reddit.com/r/reactjs/comments/17qb2by/using_react_query_to_fetch_data_for_tanstack/ I made two changes. One is to use a placeholder empty array for table initialization until the data gets fetched and store it in a useMemo that gets changed on every server data change. The other change is to import axios as import axios from 'axios' rather than use a named import like import { Axios } from 'axios'.

The following is my code now:

import {
  useReactTable,
  flexRender,
  getCoreRowModel,
} from "@tanstack/react-table";
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";

export const Employees = (props) => {
  const columns = useMemo(
    () => [
      {
        accessorKey: "employeeId",
        header: "ID",
        footer: "ID",
      },
      {
        accessorKey: "employeeName",
        header: "Name",
        footer: "Name",
      },
      {
        accessorKey: "employeeDescription",
        header: "Description",
        footer: "Description",
      },
    ],
    []
  );

  const { data: serverData } = useQuery({
    queryKey: ["employees"],
    queryFn: async () => {
      const result = await axios.get(props.path + "/api/employees", {
        headers: {
          Authorization: localStorage.getItem("token"),
        },
      });
      return result.data;
    },
  });

  const data = useMemo(() => serverData ?? [], [serverData]);

  const table = useReactTable({
    columns,
    data,
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <>
      <table>
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id}>
                  {flexRender(
                    header.column.columnDef.header,
                    header.getContext()
                  )}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <td key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
};