如何在NextJS 13 App Router中实现页面向布局组件传数据?
Next.js 13 App Router 页面向嵌套布局传递动态标题的解决方案
在Next.js 13的App Router嵌套布局场景下,页面向布局传递动态标题可以通过以下几种实用方法实现:
方法一:使用 React Context(通用方案)
通过创建Context在页面和布局之间共享数据,适合需要传递多个数据的场景。
1. 创建标题Context
// app/users/TitleContext.tsx 'use client'; import { createContext, useContext, useState, ReactNode } from 'react'; type TitleContextType = { setPageTitle: (title: string) => void; }; const TitleContext = createContext<TitleContextType | undefined>(undefined); export function TitleProvider({ children }: { children: ReactNode }) { const [pageTitle, setPageTitle] = useState(''); return ( <TitleContext.Provider value={{ setPageTitle }}> {/* 布局中渲染标题 */} <h1>{pageTitle}</h1> {children} </TitleContext.Provider> ); } export function useTitleContext() { const context = useContext(TitleContext); if (!context) { throw new Error('useTitleContext must be used within a TitleProvider'); } return context; }
2. 在布局中引入Provider
// app/users/layout.tsx import { TitleProvider } from './TitleContext'; export default function UsersLayout({ children }: { children: ReactNode }) { return <TitleProvider>{children}</TitleProvider>; }
3. 在页面中设置标题
// app/users/page.tsx 'use client'; import { useTitleContext } from './TitleContext'; import { useEffect } from 'react'; export default function Users() { const { setPageTitle } = useTitleContext(); // 组件挂载后设置标题 useEffect(() => { setPageTitle('Users'); }, [setPageTitle]); return ( <> {/* 页面内容 */} </> ); }
方法二:利用 generateMetadata + useMetadata(Next.js 原生方案,推荐)
符合App Router的设计思路,同时能同步页面元数据和布局标题。
1. 页面中定义generateMetadata
// app/users/page.tsx export async function generateMetadata() { return { title: 'Users', }; } export default function Users() { return ( <> {/* 页面内容 */} </> ); }
2. 在布局中获取并渲染标题
// app/users/layout.tsx 'use client'; import { useMetadata } from 'next/headers'; export default function UsersLayout({ children }: { children: ReactNode }) { const metadata = useMetadata(); return ( <> <h1>{metadata.title}</h1> {children} </> ); }
注意:
useMetadata是Next.js 13.4+提供的客户端钩子,仅能在客户端组件中使用。
方法三:通过React插槽传递标题
无需额外依赖,利用React Children遍历实现标题传递。
1. 创建PageTitle占位组件
// app/users/PageTitle.tsx export default function PageTitle({ children }: { children: string }) { return null; // 不在页面中渲染,仅作为传递载体 }
2. 在布局中提取标题
// app/users/layout.tsx 'use client'; import { useState, useEffect, ReactNode } from 'react'; import PageTitle from './PageTitle'; export default function UsersLayout({ children }: { children: ReactNode }) { const [pageTitle, setPageTitle] = useState(''); useEffect(() => { React.Children.forEach(children, (child) => { if (React.isValidElement(child) && child.type === PageTitle) { setPageTitle(child.props.children); } }); }, [children]); return ( <> <h1>{pageTitle}</h1> {children} </> ); }
3. 在页面中使用PageTitle组件
// app/users/page.tsx import PageTitle from './PageTitle'; export default function Users() { return ( <> <PageTitle>Users</PageTitle> {/* 页面内容 */} </> ); }
内容的提问来源于stack exchange,提问作者RomkaLTU
相关产品推荐
相关产品推荐

