Next 13中如何在服务端组件取数并传递给客户端组件使用?
Next 13 数据列表生成按钮的两种实现方案
你完全不需要只用全客户端组件实现,服务端组件取数后传给客户端组件渲染按钮是更推荐的做法,下面分两种场景说明:
一、服务端组件取数 + 客户端组件渲染按钮(优先推荐)
Next 13 默认的页面/组件都是服务端组件,你可以直接在服务端组件里写异步代码获取数据,再把数据作为 props 传给加了 'use client' 指令的客户端组件——客户端组件负责处理按钮的交互逻辑(比如点击事件),服务端组件负责数据获取和静态内容渲染,这种分工能最大化利用服务端渲染的优势(快、SEO友好)。
代码示例
服务端组件(比如 app/page.tsx):
// 无需加任何指令,默认就是服务端组件 async function fetchButtonData() { // 这里写你的数据获取逻辑,比如调用后端接口 const res = await fetch('https://your-api-endpoint/button-list', { cache: 'no-store' // 根据需求配置缓存策略 }); return res.json(); } export default async function HomePage() { const buttonList = await fetchButtonData(); return ( <div className="button-group"> {/* 把数据传给客户端组件 */} <InteractiveButtonList buttons={buttonList} /> </div> ); }
客户端组件(比如 app/components/InteractiveButtonList.tsx):
// 必须加 'use client' 声明这是客户端组件 'use client'; interface ButtonItem { id: string; text: string; } interface ButtonListProps { buttons: ButtonItem[]; } export default function InteractiveButtonList({ buttons }: ButtonListProps) { const handleButtonClick = (buttonId: string) => { // 这里写按钮的交互逻辑,比如跳转、弹窗、发请求等 console.log(`按钮 ${buttonId} 被点击了`); }; return ( <> {buttons.map(btn => ( <button key={btn.id} onClick={() => handleButtonClick(btn.id)} style={{ margin: '0 8px 8px 0', padding: '8px 16px' }} > {btn.text} </button> ))} </> ); }
二、全客户端组件实现(仅特定场景使用)
如果你的数据获取必须依赖客户端状态(比如用户登录后的身份信息、动态变化的路由参数),或者需要在客户端触发数据重新获取,那可以用全客户端组件实现——通过 useEffect 或者 SWR、React Query 这类数据请求库在客户端拉取数据,再渲染按钮。
代码示例
'use client'; import { useState, useEffect } from 'react'; interface ButtonItem { id: string; text: string; } export default function FullClientButtonList() { const [buttons, setButtons] = useState<ButtonItem[]>([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchData() { const res = await fetch('https://your-api-endpoint/button-list'); const data = await res.json(); setButtons(data); setLoading(false); } fetchData(); }, []); if (loading) return <div>加载中...</div>; const handleClick = (id: string) => { console.log(`点击了按钮 ${id}`); }; return ( <div className="button-group"> {buttons.map(btn => ( <button key={btn.id} onClick={() => handleClick(btn.id)} style={{ margin: '0 8px 8px 0', padding: '8px 16px' }} > {btn.text} </button> ))} </div> ); }
总结
优先选择第一种方案,服务端取数能减少客户端请求、提升首屏加载速度,对 SEO 更友好;只有当数据获取必须依赖客户端环境时,再考虑全客户端组件实现。
内容的提问来源于stack exchange,提问作者Richard Ryan Garcia
相关产品推荐
相关产品推荐

