在 Next.js 14 中我可以使用 Tanstack React Table 中的服务器组件吗?

问题描述 投票:0回答:1

我有客户桌;我想使用 Tanstack React Table 因为它的分页、过滤...... 在一列中,我需要获取有关客户的更多数据(例如有关客户的报告简报)。 我知道列应该是客户端组件,但我也知道客户端组件可以包含服务器组件,所以我想也许我可以使用服务器组件来获取每行的额外数据。 这些是我的文件:

仪表板.tsx:

import { columns } from '@/app/dashboard/components/columns';
import { DataTable } from '@/app/dashboard/components/data-table';
import { Client, ClientSchema, fetchClients } from '@/models/client';

// Simulate a database read for tasks.

export default async function Dashboard({ clients }: { clients: Client[] }) {
  return (
    <div className="">
      <DataTable data={clients} columns={columns} />
    </div>
  );
}

data-table.tsx(来自 shadcn ui)

'use client';

import * as React from 'react';
import {
  ColumnDef,
  ColumnFiltersState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';

import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@ui/table';

import { DataTablePagination } from './data-table-pagination';
import { DataTableToolbar } from './data-table-toolbar';

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
}

export function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData, TValue>) {
  const [rowSelection, setRowSelection] = React.useState({});
  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
  const [sorting, setSorting] = React.useState<SortingState>([]);

  const table = useReactTable({
    data,
    columns,
    state: {
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
    },
    enableRowSelection: true,
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  });

  return (
    <div className="space-y-4">
      <DataTableToolbar table={table} />
      <div className="rounded-md border">
        <Table>
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map((header) => {
                  return (
                    <TableHead key={header.id} colSpan={header.colSpan}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(header.column.columnDef.header, header.getContext())}
                    </TableHead>
                  );
                })}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
                  {row.getVisibleCells().map((cell) => (
                    <TableCell key={cell.id}>
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell colSpan={columns.length} className="h-24 text-center">
                  No results.
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      <DataTablePagination table={table} />
    </div>
  );
}

列.tsx

'use client';
import { ColumnDef, createColumnHelper } from '@tanstack/react-table';
import { Client } from '@/models/client';
import RowReports from './row-reports';
const columnHelper = createColumnHelper<Client>();

export const columns: ColumnDef<Client>[] = [
  {
    accessorKey: 'name',
    cell: (props) => {
      const row: any = props.row;
      return (
        <div className="flex space-x-2">
          <span className="max-w-[200px] truncate font-medium">{row.original.name}</span>
        </div>
      );
    },
  },
  columnHelper.display({
    id: 'id',
    cell: (props) => (
      <div>
        <RowReports clientId={props.row.original.id} />
      </div>
    ),
  }),
];

行报告.tsx

'use server';
import { Client } from '@/models/client';
import { fetchInitialReport } from '@/models/initial-report';

async function RowReport({ clientId }: { clientId: string }) {
  return <div>{clientId}</div>;
}

export default RowReport;

问题是我收到 1 个错误:

未处理的运行时错误错误:客户端组件尚不支持 async/await, 仅服务器组件。这个错误往往是由于不小心造成的 将

'use client'
添加到最初为 服务器。

开发工具控制台中出现一个警告:

警告:渲染不同组件 (

Router
) 时无法更新组件 (
proxy
)。要找到
proxy

中错误的 setState() 调用

第一个问题也是最重要的:我的架构正确吗?

我应该使用客户端而不是服务器端来获取与行相关的额外数据吗?

我的方法可以修正吗?

谢谢

next.js next.js14 react-server-components tanstack tanstack-table
1个回答
0
投票

“但我也知道客户端组件可以包含服务器组件”

这是不正确的,您无法将服务器组件导入客户端组件

您只能将服务器组件作为道具传递给客户端组件

每当您将服务器组件导入客户端组件时,

"ues server"
将被忽略,该组件将被视为客户端组件,因此,您会看到错误客户端组件尚不支持async/await

由于

coulmns
被用作
prop
而不是组件,这将使
row-reports
很难作为
children
传递,因此,它不应该是服务器组件。

我的架构正确吗?

是的,没关系,您只需要从 row-reports.tsx 文件中删除两个内容,

'use server'
async
关键字,因为它会导致错误,而且您也不会等待任何内容,因此这里不需要。

© www.soinside.com 2019 - 2024. All rights reserved.