TanStack react table Cannot read properties of undefined (reading 'length')

2.3k views Asked by At

I want to use a React library so i tried looking for a library and saw this tanstack v8 table. I followed a tutorial on basic table but im getting some errors.

//Parent next component

'use client'
import React, { useEffect, useState } from 'react'
import  BasicTable  from '../components/BasicTable'
import axios from 'axios';

export default function Vendor() {
  const [defaultData, setDefaultData] = useState(null)

  useEffect(() => {
    const generateData = async() => {
      axios.get('https://jsonplaceholder.typicode.com/posts')
      .then((response) => setDefaultData(response.data))
    }
    generateData()
  }, [])

  const columns = [
    {
      id: 1,
      label: 'user ID',
      accessorKey: 'userID'
    },
    {
      id: 2,
      label: 'id',
      assecorKey: 'id'
    },
    {
      id: 3,
      label: 'body',
      accesorKey: 'body'
    },
    {
      id: 4,
      label: 'title',
      assecorKey: 'title'
    },

  ]
  return (
    <div>
      <h1>Vendor</h1>
      <BasicTable  data={defaultData} columns={columns}/>
    </div>
  )
}

The data that i'm getting from the api is these:

(100) [{0
: 
body
: 
"quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
id
: 
1
title
: 
"sunt aut facere repellat provident occaecati excepturi optio reprehenderit"
userId
: 
1}]

BasicTable component

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

export default function BasicTable({ data, columns }) {
  const dataTable = useMemo(() => data);
  const table = useReactTable({
    dataTable,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });
  return (
    <div>
      Basic table
      <div className="border-solid border-2 rounded mt-5">
        <table>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id}>
                  {flexRender(
                    header.column.columnDef.label,
                    header.getContext()
                  )}
                </th>
              ))}
            </tr>
          ))}
          <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>
            ))}
            <tr>
              <td>id</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  );
}

I'm getting errors when i'm mapping the data rows. I'm new to using this library. I've already check and it seems that I'm getting the erros from the table.getRowModel()

5

There are 5 answers

3
Marko Sladojevic On

Have you tried awaiting the API response? If that doesn't work, try initializing the table with mock data, to see if that works.

3
Fulvia On

useReactTable accepts an options object with the key data, but you're passing it as dataTable. Try:

 const table = useReactTable({
    data: dataTable,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });
0
Felix Arjuna On

You have to make sure that the data you are passing to the BasicTable is not undefined. You can fixed it by adding a check before passing the data to the BasicTable component.

'use client'
import React, { useEffect, useState } from 'react'
import  BasicTable  from '../components/BasicTable'
import axios from 'axios';

export default function Vendor() {
  const [defaultData, setDefaultData] = useState(null)

  useEffect(() => {
    const generateData = () => {
      axios.get('https://jsonplaceholder.typicode.com/posts')
      .then((response) => setDefaultData(response.data))
    }
    generateData()
  }, [])

  const columns = [
    {
      id: 1,
      label: 'user ID',
      accessorKey: 'userID'
    },
    {
      id: 2,
      label: 'id',
      assecorKey: 'id'
    },
    {
      id: 3,
      label: 'body',
      accesorKey: 'body'
    },
    {
      id: 4,
      label: 'title',
      assecorKey: 'title'
    },

  ]

  if (defaultData === undefined) {
    return <div>Loading ... </div>
  }

  return (
    <div>
      <h1>Vendor</h1>
      <BasicTable  data={defaultData} columns={columns}/>
    </div>
  )
}

It would be better if you could implement the data fetching logic using the TanStack/ReactQuery Library, as it has the isLoading state to check if data is already available.

An implementation example would be something like this:

'use client'
import React, { useEffect, useState } from 'react'
import  BasicTable  from '../components/BasicTable'
import axios from 'axios';

const columns = [
  {
    id: 1,
    label: 'user ID',
    accessorKey: 'userID'
  },
  {
    id: 2,
    label: 'id',
    assecorKey: 'id'
  },
  {
    id: 3,
    label: 'body',
    accesorKey: 'body'
  },
  {
    id: 4,
    label: 'title',
    assecorKey: 'title'
  },
]

export default function Vendor() {
  const {data: defaultData, isLoading} = useQuery({
    queryFn: () => {
      return axios.get('https://jsonplaceholder.typicode.com/posts')
    }
  })

  if (isLoading) {
    return <div>Loading ... </div>
  }

  return (
    <div>
      <h1>Vendor</h1>
      <BasicTable  data={defaultData} columns={columns}/>
    </div>
  )
}
0
Alex P On

Make sure your data is not asyncronous. If the data is not yet ready, the table would throw this exception, while still working correctly. Render the table only if the array you're passing to the component is valid and has the right structure.

0
Joseph Owigo On

Try using react useMemo I struggle for days

 const data =  useMemo(() => defaultData,[])