遵循 Shadcn 数据表 文档中的示例。当我在
columns.tsx
中调用 trpc 的 useMutation 时(参见下面 DropdownMenuItem 中的 onClick 事件),我得到了错误:
“无效的钩子调用。钩子只能在函数组件的主体内部调用”。
我该如何处理这个行删除突变?
app
└── payments
├── columns.tsx
├── data-table.tsx
└── page.tsx
页面.tsx
import { Payment, columns } from "./columns"
import { DataTable } from "./data-table"
async function getData(): Promise<Payment[]> {
// Fetch data from your API here.
return [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "[email protected]",
},
// ...
]
}
export default async function DemoPage() {
const data = await getData()
return (
<div>
<DataTable columns={columns} data={data} />
</div>
)
}
列.tsx
"use client"
import { ColumnDef } from "@tanstack/react-table"
import { MoreHorizontal } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export const columns: ColumnDef<Payment>[] = [
// ...
{
id: "actions",
cell: ({ row }) => {
const payment = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => {
const mutation = api.transaction.delete.useMutation();
mutation.mutate({ id });
}}
>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
},
},
// ...
]
您想要将
columns
从 ColumnDef<T>
数组更改为返回 ColumnDef<T>
数组的函数。然后,您可以将突变传递给 columns
函数,如下所示:
列.tsx
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
export function columns(
mutateAsync: (id: string) => Promise<void>,
): ColumnDef<Payment>[] {
return [
// ...
{
id: "actions",
cell: ({ row }) => {
const payment = row.original;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem onClick={() => mutateAsync(payment.id)}>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
// ...
];
}
演示数据表.tsx
"use client";
import { columns } from "./columns";
import { DataTable } from "./data-table";
import { api } from "@/trpc/client";
export function DemoDataTable({ data }: { data: Payment[] }) {
const { mutateAsync } = api.transaction.delete.useMutation();
return <DataTable columns={columns(mutateAsync)} data={data} />;
}
页面.tsx
import { Payment, columns } from "./columns";
import { DataTable } from "./data-table";
import { DemoDataTable } from "./demo-data-table";
async function getData(): Promise<Payment[]> {
// Fetch data from your API here.
return [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "[email protected]",
},
// ...
];
}
export default async function DemoPage() {
const data = await getData();
return (
<div>
<DemoDataTable data={data} />
</div>
);
}
但这确实需要您创建一个中间数据表客户端组件,您可以在其中从 trpc 获取突变并将它们传递给
columns
函数。