Next.js中_app.js共享布局实现服务端渲染的问题及解决
在Next.js中实现共享布局菜单的服务端渲染(SSR)
我在开发Next.js应用时遇到菜单无法服务端渲染的问题:应用的共享布局SiteLayout原本通过useEffect在客户端请求API获取菜单数据,导致菜单不会出现在页面源码中。最终通过在_app.js的MyApp组件上添加getInitialProps方法,在服务端一次性获取菜单数据并传入页面props,解决了这个问题。
原问题代码
pages/_app.js
function MyApp({ Component, pageProps }) { return <Provider store={store}><SiteLayout><Component {...pageProps} /></SiteLayout></Provider> }
layouts/SiteLayout.js
export default function SiteLayout({ children }) { const dispatch = useDispatch() useEffect(() => { fetch("testlink", { headers: { "Content-Type": "application/x-www-form-urlencoded" }, method: 'POST', body: "client=web" }) .then(response => response.json()) .then(data => dispatch(addFeed(data))) }, []) return ( <> <Menu /> {children} </> ) }
解决方案
步骤1:给MyApp添加getInitialProps方法
在pages/_app.js中为MyApp添加getInitialProps,在服务端请求API获取菜单数据,并将数据注入pageProps:
MyApp.getInitialProps = async function (context) { // 注意:原代码中"testlik"为拼写错误,已修正为"testlink" const data = await fetch("testlink", { headers: { "Content-Type": "application/x-www-form-urlencoded" }, method: 'POST', body: "client=web" }).then(response => response.json()) return { pageProps:{ menu: data?.data?.menu ?? null } } }
步骤2:修改SiteLayout接收并使用服务端数据
修改layouts/SiteLayout.js,接收menu props,直接将服务端获取的数据同步到状态管理库,无需再在客户端发起请求:
export default function SiteLayout({ children, menu }) { const dispatch = useDispatch() // 服务端已获取数据,直接同步到store useEffect(() => { if (menu) { dispatch(addFeed({ data: { menu } })) } }, [menu, dispatch]) return ( <> <Menu /> {children} </> ) }
原理说明
getInitialProps在Next.js首次请求时会在服务端执行,将获取到的数据作为props传递给MyApp- 共享布局
SiteLayout接收服务端传来的菜单数据,直接同步到状态管理库,避免了客户端二次请求 - 菜单数据会在服务端渲染时被注入页面源码,实现了SSR效果
内容的提问来源于stack exchange,提问作者Orçun
相关产品推荐
相关产品推荐

