使用 Next.js、Tanstack Table 和 Typescript 开始使用表格

2025-06-08

使用 Next.js、Tanstack Table 和 Typescript 开始使用表格

你有没有想过,一些管理面板是如何高效、舒适地管理用户的?好吧,表格来帮你!

它们是一种高效的方式,可以显示大量信息,并拥有良好的用户体验和设计。然而,之前你需要使用一些库和依赖项,例如 Material UI Table;这是一个很好的库,但问题是它的大小大约有 300kb!你需要将所有 JavaScript 代码都传递给客户端,效率很低。

魔方。图片由 Alexander Gray 在 Unsplash 上发布。

时代变了,现在我们有了 Tanstack Table 和 Shadcn/UI 等替代方案。这些优秀的 UI 库支持 Typescript,让我们能够轻松构建直观专业的表格。

这就是为什么在本指南中您将学习如何使用 Next.js(一个基于 React 的现代全栈框架)、Shadcn/UI(一个用于 React 的出色现代 UI 库)和 JSONPlaceholder 作为我们的模型数据来构建表格。

让我们开始吧!

代码。图片来自 Unsplash 上的 Ferenc Almasi。

我们将要构建什么

我们将使用 Shadcn/UI、Next.js、Tanstack Table 和 JSONPlaceholder 构建一个用于显示用户的表格。阅读本指南并运用上述技术后,您将能够处理真实数据和表格,从而交付更高质量的产品和软件。

最终项目

项目要求

为了能够理解并充分利用本教程,您需要Node.js 18.17在计算机上安装或升级到本教程,对 React 和 Next.js 以及如何使用第三方库有深入的了解。

安装 Next.js 和 Shadcn/UI

我们将使用官方网站文档中的以下命令安装 Next.js:

npx create-next-app@latest

使用您喜欢的名称来命名您的项目,因为我们将使用 Typescript 和 App Router,所以我们将进行以下设置:

Would you like to use TypeScript? Yes
Would you like to use ESLint? Yes
Would you like to use Tailwind CSS? Yes
Would you like to use src/ directory? Yes
Would you like to use App Router? (recommended) Yes
Would you like to customize the default import alias (@/*) Yes
What import alias would you like configured? @/*

要了解有关 Next.js 安装过程的更多信息,可以查看Next.js 官方文档

现在,一旦依赖项安装完毕,请转到项目根文件夹并安装 Shadcn/UI:

npx shadcn-ui@latest init

您可以选择最合适的设置来设置您的components.json文件。这里会显示您的 Shadcn/UI 设置。

在使用 Next.js 的官方 Shadcn/UI 安装文档中了解有关使用 Next.js 安装 Shadcn/UI的过程的更多信息

安装Shadcn/UI数据表和Tanstack表

现在您已经安装了 Shadcn/UI,是时候从库中安装表格组件了。该组件可以使用 Tanstack Table 进行扩展,因此我们还需要安装该依赖项。

使用以下命令从 Shadcn/UI 安装表组件:

npx shadcn-ui@latest add table

并安装 Tanstack Table,它在底层使用 React Table,并允许您在将来添加过滤和分页功能:

npm install @tanstack/react-table

请参阅官方TanStack 表文档

现在我们可以开始获取数据并创建 Typescript 类型。

获取数据

在实际应用中,你会使用实际的 API 端点和实际的客户端数据。但在本教程中,我们将使用 JSONPlaceholder。

那么这项服务到底是什么呢?根据官方网站的介绍:

JSONPlaceholder 是一个免费的在线 REST API,您可以在需要一些虚假数据时使用它。

在这种情况下,我们将使用以下端点获取虚构用户数据:

https://jsonplaceholder.typicode.com/users

JSONPlaceholder 用户端点的响应

如你所见,我们获取的数据非常庞大,你可能会想自己创建类型。我不建议你这样做,而是建议使用像 Transform Tools 这样的网站。这个网站允许我们将文件转换为其他格式,例如将 JSON 转换为 Typescript 类型或 React Props。

复制从 API 获取的响应数据并将其粘贴到此处:https://transform.tools/json-to-typescript

src在你的文件中创建一个新文件types.ts,并粘贴你之前使用的工具的界面。由于这是一个小项目,你需要将项目的类型保存在那里。请记住,随着项目规模的扩大,你需要为类型创建和组织不同的文件夹。

现在,在对 TS 接口进行一些调整之后,您的数据可能如下所示:



// src/types.ts
export interface User {
  id: number
  name: string
  username: string
  email: string
  address: Address
  phone: string
  website: string
  company: Company
}

export interface Address {
  street: string
  suite: string
  city: string
  zipcode: string
  geo: Geo
}

export interface Geo {
  lat: string
  lng: string
}

export interface Company {
  name: string
  catchPhrase: string
  bs: string
}


Enter fullscreen mode Exit fullscreen mode

获取数据并创建服务

首先,在我们的src文件夹中创建一个名为 的新文件夹services。在这个文件夹中,我们将创建负责获取数据的异步函数。

创建一个名为 的新文件index.ts,因为我们目前只需要一个文件。记得明确添加返回类型。



// src/services/index.ts
import { User } from "@/types";

const getUsers = async (): Promise<User[]> => {
  const data = await fetch("https://jsonplaceholder.typicode.com/users");

  return data.json();
};

export default getUsers;



Enter fullscreen mode Exit fullscreen mode

列及其使用方法

创建服务后,您可以定义表的列。列是定义表外观的核心。它们定义要显示的数据,以及如何格式化、排序和过滤数据。

创建一个名为 的新文件columns.tsx。我们将显示用户的以下字段:

  • 用户名
  • 电子邮件
  • 电话号码
  • 姓名

因此我们可以创建如下列:



"use client"

import { ColumnDef } from "@tanstack/react-table"
import { User } from "@/types"

export const columns: ColumnDef<User>[] = [
  {
    accessorKey: "username",
    header: "Username",
  },
  {
    accessorKey: "email",
    header: "Email",
  },
  {
    accessorKey: "phone",
    header: "Phone Number",
  },
  {
    accessorKey: "name",
    header: "Name"
  }
]


Enter fullscreen mode Exit fullscreen mode

这段代码发生了什么?首先,我们创建列定义,并ColumnDef从 Tanstack Table 导入类型定义。这是一个泛型类型,所以我们添加想要推断的类型,在本例中,它User来自我们的类型。

我们创建一个数组,其中包含要在表格中显示的对象定义。每个对象定义都包含属性accessorKeyheaderaccessorKey表示我们将要使用的核心对象字段,header表示该属性在表格中的显示标题。

在官方 Shadncn/UI 文档中了解有关列定义的更多信息

数据表及其用途

现在是时候创建一个可重复使用的<DataTable />组件来呈现我们的表格了。

转到ui我们components文件夹内的名为 的文件夹src。创建一个名为 的新文件data-table.tsx

您将使用来自官方 Shadcn/UI 文档的以下代码:



// src/components/ui/data-table.tsx
"use client"

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

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

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

export function DataTable<TData, TValue>({
  columns,
  data,
}: DataTableProps<TData, TValue>) {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  })

  return (
    <div className="rounded-md border">
      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow key={headerGroup.id}>
              {headerGroup.headers.map((header) => {
                return (
                  <TableHead key={header.id}>
                    {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>
  )
}


Enter fullscreen mode Exit fullscreen mode

让我们看看这段代码是如何工作的:

  1. 导入:该组件从@tanstack/react-table我们之前安装的表格组件中导入必要的功能和组件@/components/ui/table

  2. Props:DataTable 组件接收两个 props:columnsdatacolumns表示列定义数组,data表示要在表格中显示的数据。

  3. useReactTable Hook:在组件内部,此useReactTable钩子用于创建表实例。它接受datacolumnsgetCoreRowModel等参数。

  4. 渲染表头:该组件通过映射从表实例获取的表头组来渲染表头。对于每个表头组,它会映射相应的表头,并TableHead为每个表头渲染一个组件。

  5. 渲染主体:该组件通过映射从表实例获取的行来渲染表主体。对于每一行,它会渲染一个TableRow组件,并根据该行是否被选中来设置其 data-state 属性。在每一行中,它会映射可见单元格,并为每个单元格渲染一个 TableCell 组件。

  6. FlexRender:该flexRender函数用于根据提供的上下文有条件地渲染每个标题和单元格的内容。

  7. 无结果消息:如果没有要显示的行,组件将呈现一个跨越所有列TableRow的单个消息TableCell,显示“无结果”消息。

在第一页显示表格

src/app/page.tsx让我们使用迄今为止构建的内容通过以下代码来设置我们的表格:



import { columns } from "@/app/columns";
import { DataTable } from "@/components/ui/data-table";
import getUsers from "@/services";

export default async function Home() {

  const data = await getUsers();

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <DataTable columns={columns} data={data} />
    </main>
  );
}


Enter fullscreen mode Exit fullscreen mode

该代码按以下方式工作:

  1. 导入:代码从@/app/columns文件导入列定义,并DataTable@/components/ui/data-table文件导入组件。此外,它还getUsers从导入函数@/services

  2. 获取数据:在Home函数内部,getUsers异步调用该函数来获取用户数据。该函数向 API 端点发出 HTTP 请求以检索数据。

  3. 渲染:获取数据后,它会DataTable连同列定义一起作为 props 传递给组件。DataTable组件会根据提供的数据和column定义渲染表格 UI。

  4. 服务器端渲染:使用 Next.js 服务器端渲染 (SSR)。服务器组件允许直接在组件内部获取数据,从而实现服务器端数据渲染。在这种情况下,getUsers会直接在组件内部调用 来获取用户数据。

最终结果

如果您正确地遵循了这些步骤,您的最终结果应该是这样的:

决赛桌

结论

恭喜您到达此处!您已经学习了如何使用 Tanstack Table、Next.js 和 ShadcnUI 创建专业的表格。您还学习了如何连接到 JSONPlaceholder API 以及如何使用 API 端点。

您还可以在未来实现分页、过滤或排序功能,以不断提升您在 Web 开发中使用表格的技能。我将在未来创建更多关于此主题的高级指南。

非常感谢您阅读本教程,我希望您学到了一些新东西!

链接链接 https://dev.to/franciscolunadev82/getting-start-with-tables-using-nextjs-tanstack-table-and-typescript-2aig
PREV
Next.js 和 GraphQL:全栈开发的完美组合
NEXT
为什么 Rust 可能是当今开发人员的明智选择?