Problem:
UPDATE
My answer is not working: Next JS 13 does not recommend adding _app.tsx
or _document.tsx
, instead, we should use the default layout.tsx
.
With my solution, Navbar and Footer are added to all pages but there is a console error:
Uncaught Error: invariant expected app router to be mounted
which requires the html
and body
tags in layout.tsx
. However, if I change layout.tsx
back to it’s default, the previously added _document.tsx
adds an extra html
tag to the page HTML, causing the following error:
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>.
I’m still looking for a solution.
I have a Next JS app, the version is 13.5.4, its structured like this:
- pages
-- about.tsx
- src
-- app
--- layout.tsx
--- page.tsx
In order to not repeat code, I changed the default layout.tsx to this:
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>
)
}
My goal is to have Navbar and Footer on every page by default. Now the problem is, they are on homepage, i.e. applied to page.tsx. But they are not on /about. Any idea why?
Here is the navbar.tsx which routes to the /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>
)
}
Solution:
I have found another solution:
The pages
folder should be empty, everything should be in /src/app
The correct project layout should be:
|-project
|--src
|---app
|----about
|-----page.tsx
|----components
|-----Navbar
|------Navbar.tsx
|-----Footer
|------Footer.tsx
|----globals.scss
|----layout.tsx
|----page.tsx
The layout.tsx
should be:
import { Navbar } from "@/app/components/Navbar/navbar";
import { Footer } from "@/app/components/Footer/footer";
import './globals.scss'
interface LayoutProps {
children: React.ReactNode;
}
export default function RootLayout({ children }: LayoutProps) {
return (
<html lang="en">
<body>
<main className="flex min-h-screen flex-col items-center justify-between p-24 main">
<Navbar />
{children}
<Footer />
</main>
</body>
</html>
)
}
Then src/app/about/page.tsx
should be
export default function About() {
return (
<div>
About me
</div>
)
}
Then there is no console error, the navbar and footer are on every page without defining in each page .tsx
file.