Next.js中Axios获取数据无法在TanStack Table展示的问题
问题:Next.js中Axios获取的数据无法在TanStack Table中展示
- 在
ProjectsTableBlock组件的help1与help2之间能正常打印Axios获取到的数据 - 但数据无法在
Table组件的dell1与dell2之间打印,也无法在表格HTML中展示 - 硬编码数据测试时,TanStack Table功能完全正常
相关代码
ProjectsTableBlock.tsx
import React, { ReactNode, useEffect } from "react"; import Block from "./Block"; import Button from "../Button"; import Table from "../Table"; import { createColumnHelper } from "@tanstack/react-table"; import axios from "axios"; type ProjectsTableBlockProps = { block_span: string; children: ReactNode; }; type Project = { project_id: number; name: string; description: string; organization_id: number; }; const columnHelper = createColumnHelper<Project>(); const columns = [ columnHelper.accessor("project_id", { header: () => "Project ID", cell: (info) => info.getValue(), footer: (info) => info.column.id, }), columnHelper.accessor("name", { cell: (info) => <i>{info.getValue()}</i>, header: () => "Name", footer: (info) => info.column.id, }), columnHelper.accessor("description", { header: "Description", cell: (info) => info.getValue(), footer: (info) => info.column.id, }), columnHelper.accessor("organization_id", { header: "Organization ID", cell: (info) => info.getValue(), footer: (info) => info.column.id, }), ]; export default function ProjectsTableBlock(ProjectsTableBlockProps) { const [data, setData] = React.useState<Project[]>([]); useEffect(() => { axios .get("/api/projects") .then((response) => { setData(response.data); }) .catch((error) => console.error("Error fetching projects:", error)); }, []); console.log("help1"); console.log(data); console.log("help2"); return ( <Block> <div className=" flex items-center justify-between pb-6"> <div> <h2 className="text-gray-600 font-semibold">Projects</h2> <span className="text-xs">Projects List</span> </div> <div className="flex items-center justify-between"> <div className="lg:ml-40 ml-10 space-x-8"> <Button action="Create">Create</Button> </div> </div> </div> <div> <div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto"> <div className="inline-block min-w-full shadow rounded-lg overflow-hidden"> <Table columns={columns} data={data}></Table> </div> </div> </div> </Block> ); }
Table.tsx
import { ViewColumnsIcon } from "@heroicons/react/24/outline"; import React, { useState } from "react"; import { createColumnHelper, flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table"; type TableProps = { columns: any; data: any; }; export default function Table(TableProps) { const [data, setData] = React.useState(() => [...TableProps.data]); const table = useReactTable({ data, columns: TableProps.columns, getCoreRowModel: getCoreRowModel(), }); console.log("dell1"); console.log(data); console.log("dell2"); return ( <div> <table className="min-w-full"> <thead className="bg-white border-b"> {table.getHeaderGroups().map((headerGroup) => ( <tr key={headerGroup.id}> {headerGroup.headers.map((header) => ( <th key={header.id}> {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} </th> ))} </tr> ))} </thead> <tbody> {table.getRowModel().rows.map((row) => ( <tr className="bg-white border-b" key={row.id}> {row.getVisibleCells().map((cell) => ( <td className="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap" key={cell.id} > {flexRender( cell.column.columnDef.cell, cell.getContext() )} </td> ))} </tr> ))} </tbody> </table> </div> ); }
解决方案
问题出在Table组件的内部状态逻辑:
问题根源:
Table组件用useState初始化了内部data状态,初始值是[...TableProps.data]。但这个初始化仅在组件首次挂载时执行一次,当父组件ProjectsTableBlock通过Axios获取到新数据并更新data后,子组件Table的内部状态不会同步更新——因为useState的初始值不会随props变化而重新计算。修复方法:直接移除
Table组件内部的data状态,直接使用props传入的数据即可,无需额外维护内部状态。
修复后的Table.tsx
import { ViewColumnsIcon } from "@heroicons/react/24/outline"; import React from "react"; import { flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table"; type TableProps = { columns: any; data: any; }; export default function Table({ columns, data }: TableProps) { const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), }); console.log("dell1"); console.log(data); console.log("dell2"); return ( <div> <table className="min-w-full"> <thead className="bg-white border-b"> {table.getHeaderGroups().map((headerGroup) => ( <tr key={headerGroup.id}> {headerGroup.headers.map((header) => ( <th key={header.id}> {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} </th> ))} </tr> ))} </thead> <tbody> {table.getRowModel().rows.map((row) => ( <tr className="bg-white border-b" key={row.id}> {row.getVisibleCells().map((cell) => ( <td className="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap" key={cell.id} > {flexRender( cell.column.columnDef.cell, cell.getContext() )} </td> ))} </tr> ))} </tbody> </table> </div> ); }
说明
- 直接使用props传入的
data,当父组件更新数据时,子组件会自动重新渲染,TanStack Table也会同步使用最新数据生成表格 - 移除不必要的内部状态后,组件逻辑更简洁,数据流向更清晰
内容的提问来源于stack exchange,提问作者Byverone
相关产品推荐
相关产品推荐

