You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14:如何在Server Component中使用可复用按钮组件?

解决Next.js 14中Server Component使用带onClick的Client Component问题

问题核心

Next.js 14的Server Component无法直接向Client Component传递函数类型的props(比如onClick),因为服务端无法序列化函数并传递给客户端,这就是你遇到报错的根本原因。

解决方案

方案一:抽离交互逻辑到独立Client子组件

创建一个包含交互逻辑的小型Client Component,页面(保持Server Component)只负责渲染这个子组件,无需添加'use client'。

示例代码:

  1. 创建InteractiveButton.tsx(Client Component):
"use client"
import Button from './Button'

export default function InteractiveButton() {
  const handleOnClick = () => {
    console.log(111);
  }

  return <Button onClick={handleOnClick}>Test</Button>
}
  1. 修改根页面Home.tsx(Server Component):
import InteractiveButton from '@/components/InteractiveButton'

export default function Home() {
  return (
    <main>
      <InteractiveButton />
    </main>
  )
}

方案二:让Button组件内置可配置的交互逻辑

如果按钮的交互逻辑可以通过非函数类型的props配置,直接把逻辑写到Button组件内部,避免页面传递函数。

示例代码:

  1. 修改Button组件:
"use client"
import { ButtonHTMLAttributes } from "react"

type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  logMessage?: string
}

export default function Button({ logMessage, children, ...rest }: ButtonProps) {
  const handleClick = () => {
    if (logMessage) {
      console.log(logMessage)
    }
    rest.onClick?.() // 保留原有onClick的执行逻辑
  }

  return (
    <button onClick={handleClick} {...rest}>
        {children}
    </button>
  )
}
  1. 页面使用(Server Component):
import { Button } from '@/components'

export default function Home() {
  return (
    <main>
      <Button logMessage="111">Test</Button>
    </main>
  )
}

方案三:使用React Server Actions(服务端交互场景)

如果点击逻辑需要调用服务端代码(如数据库操作、API调用),可以用Server Actions替代客户端事件处理函数,无需在页面传递函数。

示例代码:

  1. 定义Server Action:
"use server"
export async function handleServerClick() {
  // 服务端逻辑,比如写入数据库、调用外部API等
  console.log('Server side log: 111')
}
  1. 修改Button组件:
"use client"
import { ButtonHTMLAttributes } from "react"
import { handleServerClick } from './actions'

export default function Button({ children }: ButtonHTMLAttributes<HTMLButtonElement>) {
  return (
    <button onClick={handleServerClick}>
        {children}
    </button>
  )
}
  1. 页面直接渲染Button即可,保持Server Component属性。

总结

核心思路是避免在Server Component中直接传递函数给Client Component,通过封装Client子组件、配置可序列化props、使用Server Actions三种方式,既能保留页面的Server Component特性,又能实现按钮的交互功能。

内容的提问来源于stack exchange,提问作者xtreebug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:45:17