Next.js 13.5.4布局异常:layout.tsx仅作用于首页,其他页面无导航栏页脚
项目结构
- pages -- about.tsx - src -- app --- layout.tsx --- page.tsx
操作与代码
为避免代码重复,修改src/app/layout.tsx添加Navbar和Footer,期望它们默认显示在所有页面,修改后的代码如下:
import './globals.scss' import type { Metadata } from 'next' import { Inter } from 'next/font/google' import {Navbar} from "@/app/components/Navbar/navbar"; import {Footer} from "@/app/components/Footer/footer"; const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body className={inter.className}> <Navbar /> // ---- added this {children} <Footer /> // ---- added this </body> </html> ) }
Navbar组件代码(包含跳转到/about的链接):
import Link from "next/link"; export const Navbar = () => { return ( <nav> <div> <ul> <li> <Link href="/#">Home</Link> </li> <li> <Link href="/about">About</Link> </li> </ul> </div> </nav> ) }
当前问题
Navbar和Footer仅在首页显示,访问/about页面时完全不生效。
更新说明
- 尝试添加
_app.tsx或_document.tsx无效,Next.js 13官方不推荐这种方式,应使用默认的layout.tsx。 - 曾强行让导航栏和页脚显示在所有页面,但控制台出现错误:
该错误提示Uncaught Error: invariant expected app router to be mountedlayout.tsx必须包含<html>和<body>标签。 - 若恢复
layout.tsx默认内容,之前添加的_document.tsx会生成额外的<html>标签,导致 hydration 错误:Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Expected server HTML to contain a matching <html> in <div>.
解决方案
核心问题是项目同时混用了App Router(src/app目录)和Pages Router(pages目录),两者的布局逻辑完全独立:
- App Router的
RootLayout仅对src/app下的页面生效,pages/about.tsx属于Pages Router,不会继承该布局; - 同时存在
layout.tsx和_document.tsx时,两者都会渲染<html>/<body>标签,导致重复嵌套引发hydration错误。
方案一:统一使用App Router(推荐)
将Pages Router页面迁移到App Router:
- 删除
pages目录,在src/app下新建about目录,创建src/app/about/page.tsx,复制原pages/about.tsx的内容到该文件; - 保留当前
src/app/layout.tsx的写法(包含<html>、<body>、Navbar和Footer),所有App Router下的页面会自动继承这个根布局。
方案二:为Pages Router单独配置布局(仅临时过渡)
如果暂时不想迁移页面,需为Pages Router单独设置全局布局:
- 在
pages目录下创建_app.tsx,内容如下:import '../src/app/globals.scss' import type { AppProps } from 'next/app' import {Navbar} from "@/app/components/Navbar/navbar"; import {Footer} from "@/app/components/Footer/footer"; import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'] }) export default function App({ Component, pageProps }: AppProps) { return ( <div className={inter.className}> <Navbar /> <Component {...pageProps} /> <Footer /> </div> ) } - 必须删除
_document.tsx,避免和App Router的layout.tsx冲突。
额外注意点
- Navbar中的
<Link href="/#">写法错误,应改为<Link href="/">跳转首页; - 确保组件导入路径正确,比如
@/app/components/Navbar/navbar对应实际文件位置。
内容的提问来源于stack exchange,提问作者one-hand-octopus
相关产品推荐
相关产品推荐

