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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:57:01