Next.js中如何在不同路由复用公共组件且避免状态丢失?
Next.js 指定页面复用持久化侧边栏方案
方案1:页面级布局包装器(轻量实现,适合少量非关联页面)
你需要的_page_with_sidebar.js模板可以直接封装为布局组件实现:
- 新建
components/PageWithSidebar.js
import Sidebar from './Sidebar' export default function PageWithSidebar({ children }) { return ( <div className="flex min-h-screen"> <Sidebar /> <main className="flex-1"> {children} </main> </div> ) }
- 在需要侧边栏的页面直接包裹导出内容即可,以
pages/page1.js为例:
import PageWithSidebar from '../components/PageWithSidebar' function Page1() { return <div>页面1内容</div> } // 用布局组件包裹页面内容 export default () => <PageWithSidebar><Page1 /></PageWithSidebar>
注意:该方案跳转同布局页面时侧边栏会重新渲染、状态丢失,适合仅少数页面需要侧边栏且不需要持久化侧边栏状态的场景
方案2:_app.js 路由匹配布局(Pages Router 最优解,持久化侧边栏状态)
利用Pages Router中_app.js全局不卸载的特性,通过路由路径判断是否加载侧边栏布局,实现侧边栏跨页面不重渲、状态保留:
修改pages/_app.js:
import { useRouter } from 'next/router' import Sidebar from '../components/Sidebar' // 填入所有需要显示侧边栏的页面路径 const SIDEBAR_PAGES = ['/page1', '/page2'] export default function MyApp({ Component, pageProps }) { const router = useRouter() const needSidebar = SIDEBAR_PAGES.includes(router.pathname) if (needSidebar) { return ( <div className="flex min-h-screen"> <Sidebar /> <main className="flex-1"> <Component {...pageProps} /> </main> </div> ) } return <Component {...pageProps} /> }
该方案下所有指定路径的页面共享同一个Sidebar实例,跳转时不会重新渲染,useState状态完全保留。
方案3:路由组布局(App Router 最优解)
如果你使用Next.js 13+的App Router,可以直接用路由组实现指定页面共享布局,无需手动判断路径:
- 在app目录下新建带括号的路由组文件夹
(with-sidebar),所有需要侧边栏的页面都放入该文件夹下 - 在
(with-sidebar)目录下新建layout.js:
import Sidebar from '@/components/Sidebar' export default function WithSidebarLayout({ children }) { return ( <div className="flex min-h-screen"> <Sidebar /> <main className="flex-1"> {children} </main> </div> ) }
路由组不会影响实际访问路径,(with-sidebar)/page1/page.js的访问路径依然是/page1,且同组页面跳转时Sidebar不会重新渲染,状态完全保留。
内容的提问来源于stack exchange,提问作者pssngr
相关产品推荐
相关产品推荐

