Next.js 10升级至13:新布局中如何向LayoutWrapper传递pageProps
Next.js 10升级到13:向LayoutWrapper传递pageProps的解决方案
我正在把Next.js从10版本升级到13版本,原v10的pages/_app.js中会将pageProps传递给LayoutWrapper组件。但v13采用app/layout.js的新布局结构,无法直接获取pageProps,请问如何修改代码实现向LayoutWrapper传递pageProps?
原v10版本的pages/_app.js代码
import { Provider } from 'next-auth/client'; import '../styles/globals.css'; import 'react-perfect-scrollbar/dist/css/styles.css'; import LayoutWrapper from '../components/Layout/layout-wrapper'; function MyApp({ Component, pageProps }) { return ( <Provider session={pageProps.session}> <LayoutWrapper {...pageProps}> <Component {...pageProps} /> </LayoutWrapper> </Provider> ); } export default MyApp;
v13版本的app/layout.js当前代码
import { AuthProvider } from './Providers'; import '../styles/globals.css'; import LayoutWrapper from '../components/Layout/layout-wrapper'; export default function RootLayout({ children }) { return ( <> <html lang="en"> <body> <AuthProvider> <LayoutWrapper>{children}</LayoutWrapper> </AuthProvider> </body> </html> </> ); }
components/Layout/layout-wrapper.js代码
import DefaultLayout from './default'; import HomeLayout from './home'; const layouts = { default: DefaultLayout, home: HomeLayout }; const LayoutWrapper = props => { // 获取每个组件指定的布局文本值 const Layout = layouts[props.children.type.layout]; console.log('Layout', Layout); // 如果有已注册的布局,就用该布局渲染子组件 if (Layout != null) { return <Layout {...props}>{props.children}</Layout>; } // 如果没有,就用HomeLayout渲染子组件 return <HomeLayout {...props}>{props.children}</HomeLayout>; }; export default LayoutWrapper;
解决方案1:页面组件直接传递props给LayoutWrapper
在App Router的页面组件中,自行包裹LayoutWrapper并传递所需的pageProps,同时修改RootLayout移除内部的LayoutWrapper:
- 修改app/layout.js:
import { AuthProvider } from './Providers'; import '../styles/globals.css'; export default function RootLayout({ children }) { return ( <> <html lang="en"> <body> <AuthProvider> {children} {/* 页面将自行包裹LayoutWrapper */} </AuthProvider> </body> </html> </> ); }
- 在页面组件(比如app/page.js)中传递props:
import LayoutWrapper from '../components/Layout/layout-wrapper'; import { getSession } from 'next-auth/react'; async function HomePage() { // 获取原pageProps中的数据,这里以session为例 const session = await getSession(); const pageProps = { session }; return ( <LayoutWrapper {...pageProps}> {/* 页面内容 */} <h1>Home Page</h1> </LayoutWrapper> ); } export default HomePage;
这种方式适合每个页面pageProps不同的场景,但需要每个页面都手动处理。
解决方案2:用React Context全局传递pageProps
通过Context将页面的props传递给LayoutWrapper,避免每个页面重复代码:
- 创建PagePropsContext:
// app/PagePropsContext.js 'use client'; import { createContext, useContext } from 'react'; const PagePropsContext = createContext(null); export function PagePropsProvider({ children, pageProps }) { return ( <PagePropsContext.Provider value={pageProps}> {children} </PagePropsContext.Provider> ); } export function usePageProps() { const context = useContext(PagePropsContext); if (!context) { throw new Error('usePageProps必须在PagePropsProvider内部使用'); } return context; }
- 修改页面组件,用PagePropsProvider包裹:
// app/page.js import { PagePropsProvider } from './PagePropsContext'; import { getSession } from 'next-auth/react'; async function HomePage() { const session = await getSession(); const pageProps = { session }; return ( <PagePropsProvider pageProps={pageProps}> {/* 页面内容 */} <h1>Home Page</h1> </PagePropsProvider> ); } export default HomePage;
- 修改LayoutWrapper,通过usePageProps获取props:
// components/Layout/layout-wrapper.js 'use client'; import { usePageProps } from '../../app/PagePropsContext'; import DefaultLayout from './default'; import HomeLayout from './home'; const layouts = { default: DefaultLayout, home: HomeLayout }; const LayoutWrapper = ({ children }) => { const pageProps = usePageProps(); const Layout = layouts[children.type.layout]; console.log('Layout', Layout); if (Layout != null) { return <Layout {...pageProps}>{children}</Layout>; } return <HomeLayout {...pageProps}>{children}</HomeLayout>; }; export default LayoutWrapper;
- RootLayout保持原有结构不变即可。
解决方案3:直接在LayoutWrapper中获取全局数据
如果pageProps中的内容是全局通用的(比如session),可以直接在LayoutWrapper中通过对应钩子获取,无需传递:
// components/Layout/layout-wrapper.js 'use client'; import { useSession } from 'next-auth/react'; import DefaultLayout from './default'; import HomeLayout from './home'; const layouts = { default: DefaultLayout, home: HomeLayout }; const LayoutWrapper = ({ children }) => { const { data: session } = useSession(); const pageProps = { session }; const Layout = layouts[children.type.layout]; console.log('Layout', Layout); if (Layout != null) { return <Layout {...pageProps}>{children}</Layout>; } return <HomeLayout {...pageProps}>{children}</HomeLayout>; }; export default LayoutWrapper;
RootLayout无需修改,直接使用即可。
内容的提问来源于stack exchange,提问作者Gowdham GM
相关产品推荐
相关产品推荐

