Next.js 13使用Tremor图表时Value Formatter传参报错求助
解决Next.js 13 + Tremor组件库中Value Formatter函数传递报错问题
在Next.js 13项目中使用Tremor的LineChart组件时,启用valueFormatter={numberFormatter}会触发以下错误:
Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server"
问题原因
Next.js 13 App Router中,组件默认是Server Component,而Tremor的图表组件属于Client Component(依赖浏览器环境渲染)。Server Component无法直接将函数传递给Client Component,这是报错的核心原因。
解决方案
方法一:在服务器端提前格式化数据
直接在数据转换阶段完成数值格式化,避免向Client Component传递函数:
修改transformedData的处理逻辑:
const transformedData = items.map((item) => { const date = new Date(item.createdAt); return { createdAt: formatDate.format(date), // 提前在服务器端格式化数值 value: numberFormatter(item.value) }; });
随后在Linechart组件中移除valueFormatter属性:
<Linechart data={transformedData} categories={["value"]} index={"createdAt"} color={"teal"} curveType={"monotone"} maxValue={2500000} />
方法二:拆分组件,将格式化函数放在Client Component中
- 创建带
'use client'标记的Client组件(例如ClientLineChart.tsx),在内部定义格式化函数:
'use client'; import { LineChart } from "@tremor/react"; const numberFormatter = (value: number) => `${Intl.NumberFormat("us").format(value).toString()}`; export default function ClientLineChart(props: { data: any[]; categories: string[]; index: string; color: string; curveType: string; maxValue: number; }) { return ( <LineChart data={props.data} categories={props.categories} index={props.index} valueFormatter={numberFormatter} color={props.color} curveType={props.curveType} maxValue={props.maxValue} /> ); }
- 在原
DashboardNetworth组件(Server Component,无需'use client')中导入并使用该Client组件:
import { getAuthSession } from "@/lib/auth"; import { db } from "@/lib/db"; import { Card, Text, Title } from "@tremor/react"; import ClientLineChart from "./ClientLineChart"; const formatDate = new Intl.DateTimeFormat("en-US", { month: "short", year: "numeric", day: "numeric", }); const DashboardNetworth = async () => { const session = await getAuthSession(); const items = await db.item.findMany({ where: { creatorId: session?.user.id, }, }); const transformedData = items.map((item) => { const date = new Date(item.createdAt); return { createdAt: formatDate.format(date), value: item.value // 保留数值类型,由Client组件负责格式化 }; }); return ( <Card className="h-[400px]"> <div className="block sm:flex sm:justify-between"> <div> <Title>Networth</Title> <Text>Total networth over time</Text> </div> </div> <ClientLineChart data={transformedData} categories={["value"]} index={"createdAt"} color={"teal"} curveType={"monotone"} maxValue={2500000} /> </Card> ); }; export default DashboardNetworth;
内容的提问来源于stack exchange,提问作者Jordy
相关产品推荐
相关产品推荐

