You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TanStack Table渲染报错:数据未加载时触发length读取异常

TanStack React-Table 加载数据前渲染导致「Cannot read properties of undefined (reading 'length')」错误解决

问题描述

使用TanStack react-table时,表格在数据加载完成前提前渲染,触发Cannot read properties of undefined (reading 'length')错误,错误指向table.getRowModel().rows.map代码行。已尝试设置默认空数组、使用useMemo等方案未解决,怀疑useEffect使用方式存在问题。客户端渲染模式下,父组件与DataTable组件简化代码如下:

父组件代码

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

export default function MainPage() {
  const [data, setData] = useState([])

  useEffect(() => {
    const data = getReports();
    setData(data);
  }, [])

  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>Reports</h1>
      <DataTable  data={data} columns={columns}/>
    </div>
  )
}

DataTable组件代码

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

export default function DataTable({ data, columns }) {
  
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });
  return (
    <div>
      <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>
  );
}

错误原因分析

  1. 异步请求处理错误:getReports()是异步函数,直接赋值给data会得到Promise对象而非实际数据,导致传给DataTable的data为Promise,react-table无法正常解析。
  2. 列定义拼写错误:多个列的accessorKey字段拼写错误(写成assecorKey/accesorKey),react-table无法识别列字段,引发内部数据处理异常。
  3. 组件props无兜底处理:未给DataTable的data和columns设置默认值,若传入非预期值会导致表格渲染失败。

解决方案

1. 修复异步请求逻辑

父组件中正确处理异步函数,使用async/await获取数据:

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

export default function MainPage() {
  const [data, setData] = useState([])

  // 定义异步数据请求函数
  const getReports = async () => {
    try {
      const res = await axios.get('你的数据接口地址');
      return res.data;
    } catch (err) {
      console.error('数据加载失败:', err);
      return [];
    }
  };

  useEffect(() => {
    // 正确执行异步请求并更新state
    const fetchData = async () => {
      const result = await getReports();
      setData(result);
    };
    fetchData();
  }, [])

  // 修复列定义的拼写错误
  const columns = [
    {
      id: 1,
      label: 'user ID',
      accessorKey: 'userID'
    },
    {
      id: 2,
      label: 'id',
      accessorKey: 'id'
    },
    {
      id: 3,
      label: 'body',
      accessorKey: 'body'
    },
    {
      id: 4,
      label: 'title',
      accessorKey: 'title'
    },
  ]

  return (
    <div>
      <h1>Reports</h1>
      <DataTable data={data} columns={columns}/>
    </div>
  )
}

2. 增强DataTable组件健壮性

给props设置默认值,增加空数据兜底渲染:

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

export default function DataTable({ data = [], columns = [] }) {
  // 确保传入的data和columns为有效数组
  const table = useReactTable({
    data: Array.isArray(data) ? data : [],
    columns: Array.isArray(columns) ? columns : [],
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <div>
      <div className="border-solid border-2 rounded mt-5">
        <table>
          <thead>
            {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>
            ))}
          </thead>
          <tbody>
            {/* 空数据/加载中状态提示 */}
            {table.getRowModel().rows.length === 0 ? (
              <tr>
                <td colSpan={columns.length} className="text-center py-4">
                  加载中...暂无数据
                </td>
              </tr>
            ) : (
              table.getRowModel().rows.map(row => (
                <tr key={row.id}>
                  {row.getVisibleCells().map(cell => (
                    <td key={cell.id}>
                      {/* 兜底处理cell渲染逻辑 */}
                      {flexRender(cell.column.columnDef.cell || cell.getValue(), cell.getContext())}
                    </td>
                  ))}
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

3. 关键修复点总结

  • 异步函数必须通过async/await或.then()获取结果,不能直接将Promise赋值给state
  • 严格检查列定义的字段拼写,确保accessorKey正确无误
  • 给组件props设置默认值,避免非预期值导致的渲染错误

内容的提问来源于stack exchange,提问作者ams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:50:21