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

Next.js 14 App Router:服务器组件中layout.js如何向子组件传数据?

Next 14 App Router 服务器组件场景下从Layout向子组件传数据的方法

在Next 14的App Router中,只要子组件保持服务器组件身份(不使用'use client'指令、不依赖客户端专属API),完全可以从Layout向其传递数据,以下是几种可行方案:

1. 直接通过Props传递(适用于Layout内的自定义服务器组件)

如果子组件是Layout中直接引入的自定义组件,直接通过props传递数据即可,这是最直观的方式。

// app/layout.js(服务器组件)
export default async function RootLayout({ children }) {
  // 服务器端获取数据
  const layoutData = await fetch('https://api.example.com/layout-data').then(res => res.json());

  return (
    <html>
      <body>
        {/* 将数据通过props传给自定义服务器子组件 */}
        <SiteHeader data={layoutData.header} />
        {children}
      </body>
    </html>
  );
}

// app/components/SiteHeader.js(服务器组件)
export default function SiteHeader({ data }) {
  return (
    <header>
      <h1>{data.title}</h1>
      <p>{data.description}</p>
    </header>
  );
}

2. 使用React Context传递(适用于深层嵌套的服务器组件)

如果需要向多层嵌套的服务器组件传递数据,避免props drilling,可以使用React Context。注意Context的提供者和消费者都必须是服务器组件。

// app/contexts/LayoutContext.js
import { createContext, useContext } from 'react';

const LayoutContext = createContext();

export function LayoutProvider({ children, data }) {
  return (
    <LayoutContext.Provider value={data}>
      {children}
    </LayoutContext.Provider>
  );
}

export function useLayoutData() {
  return useContext(LayoutContext);
}

// app/layout.js(服务器组件)
import { LayoutProvider } from './contexts/LayoutContext';

export default async function RootLayout({ children }) {
  const layoutData = await fetch('https://api.example.com/layout-data').then(res => res.json());

  return (
    <html>
      <body>
        <LayoutProvider data={layoutData}>
          {children}
        </LayoutProvider>
      </body>
    </html>
  );
}

// app/components/DeepNestedComponent.js(服务器组件)
import { useLayoutData } from '../contexts/LayoutContext';

export default function DeepNestedComponent() {
  const data = useLayoutData();
  return <div>{data.footerText}</div>;
}

3. 共享缓存的数据获取函数(适用于路由组件如page.js)

对于路由匹配的组件(比如page.js),无法直接通过props接收Layout的数据,此时可以通过缓存的共享函数获取同一份数据,Next会自动缓存结果,避免重复请求。

// app/lib/data.js
import { unstable_cache } from 'next/cache';

// 缓存数据获取函数,设置缓存有效期
export const getLayoutData = unstable_cache(
  async () => {
    const res = await fetch('https://api.example.com/layout-data');
    return res.json();
  },
  ['layout-data-cache-key'],
  { revalidate: 3600 } // 1小时重新验证一次
);

// app/layout.js(服务器组件)
import { getLayoutData } from './lib/data';

export default async function RootLayout({ children }) {
  const layoutData = await getLayoutData();
  return (
    <html>
      <body>
        <header>{layoutData.siteName}</header>
        {children}
      </body>
    </html>
  );
}

// app/page.js(服务器组件)
import { getLayoutData } from './lib/data';

export default async function HomePage() {
  // 调用同一份缓存函数,不会重复发起请求
  const layoutData = await getLayoutData();
  return <main>{layoutData.homeContent}</main>;
}

注意事项

  • 所有方案都不需要将子组件标记为客户端组件,保持服务器组件身份即可。
  • 如果后续子组件需要转为客户端组件,需确保传递的数据是可序列化的(不能包含函数、Symbol等非序列化值)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:10:17