Omit rendering Navbar component on 404 route
Answered
Cimarrón Uruguayo posted this in #help-forum
Cimarrón UruguayoOP
In an app-router based next app, how does one check for an undefined route - i.e.,
/not-found being triggered?Answered by Ray
create a route group and put
(without-navbar)/layout.tsx <--
(with-navbar)/layout.tsx <--
not-found.tsx inside?(without-navbar)/layout.tsx <--
not-found.tsx here(with-navbar)/layout.tsx <--
<Navbar /> here120 Replies
Cimarrón UruguayoOP
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className="h-full">
<body className={cn(
inter.className,
"relative h-full font-sans antialiased"
)}>
<main className='relative flex flex-col min-h-screen'>
<Navbar />
<div className='flex-grow flex-1'>
{children}
</div>
</main>
</body>
</html>
)
}I would like
<Navbar /> to only be rendered for intended routescreate a route group and put
(without-navbar)/layout.tsx <--
(with-navbar)/layout.tsx <--
not-found.tsx inside?(without-navbar)/layout.tsx <--
not-found.tsx here(with-navbar)/layout.tsx <--
<Navbar /> hereAnswer
@Ray create a route group and put `not-found.tsx` inside?
(without-navbar)/layout.tsx <-- `not-found.tsx` here
(with-navbar)/layout.tsx <-- `<Navbar />` here
Cimarrón UruguayoOP
so two route groups?
Cimarrón UruguayoOP
hmm i tried it another way
@Ray or just one (with-navbar)
Cimarrón UruguayoOP
what about the root
page.tsx having the Navbar componentbecause page.tsx will be part of the
children in layout.tsx that get rendered rightyou don't need navbar in other page?
Cimarrón UruguayoOP
ah crap true 😅
@Ray and leave not-found at root
Cimarrón UruguayoOP
does this just have to be an empty tsx file?
no, you need to export a default component in it
import Link from 'next/link'
export default function NotFound() {
return (
<div>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href="/">Return Home</Link>
</div>
)
}something like this
@Ray ts
import Link from 'next/link'
export default function NotFound() {
return (
<div>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href="/">Return Home</Link>
</div>
)
}
something like this
Cimarrón UruguayoOP
import React from 'react'
import ErrorPage from 'next/error'
const NotFound = ({ statusCode }: { statusCode: number }) => {
return <ErrorPage statusCode={statusCode} />
}
export default NotFoundill try this
import ErrorPage from 'next/error'does this work? I've never tried it
Cimarrón UruguayoOP
but it complains that I don't have a layout.tsx in the root level
you still need a root layout
Cimarrón UruguayoOP
so when i added the layout.tsx (but removed navbar), it doesn't render the navbar
the root layout should contain the html body tag
Cimarrón UruguayoOP
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { cn } from '@/lib/utils'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'DigitalHippo',
description: 'A platform of high quality digital assets',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className="h-full">
<body className={cn(
inter.className,
"relative h-full font-sans antialiased"
)}>
<main className='relative flex flex-col min-h-screen'>
<div className='flex-grow flex-1'>
{children}
</div>
</main>
</body>
</html>
)
}root tsx
it should call
layout.tsx@Ray it should call `layout.tsx`
Cimarrón UruguayoOP
?
it is being called
(with-navbar)/layout.tsx isn't being called
yes
app/layout.tsxapp/(with-navbar)/layout.tsxCimarrón UruguayoOP
yes I have both
the second file doesn't seem to get rendered
where is the
page.tsx?Cimarrón UruguayoOP
app/page.tsxmove it to (with-navbar)
Cimarrón UruguayoOP
umm i get a hydration error now
can you show the code in app/(with-navbar)/layout.tsx
Cimarrón UruguayoOP
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { cn } from '@/lib/utils'
import Navbar from '@/components/nav/Navbar'
import '../globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'DigitalHippo',
description: 'A platform of high quality digital assets',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className="h-full">
<body className={cn(
inter.className,
"relative h-full font-sans antialiased"
)}>
<main className='relative flex flex-col min-h-screen'>
<Navbar />
<div className='flex-grow flex-1'>
{children}
</div>
</main>
</body>
</html>
)
}you don't need html, body, main tag here
Cimarrón UruguayoOP
wait what
why
just do
<>
<Navbar />
<div className='flex-grow flex-1'>
{children}
</div>
</>because app/(with-navbar)/layout.tsx is nested in app/layout.tsx
check the page element and you will see
Cimarrón UruguayoOP
alright let me have a look
also, remove the css import in app/(with-navbar)/layout.tsx
import it in app/layout.tsx is fine
Cimarrón UruguayoOP
and the metadata?
hmm it depend
if you want to have different title
Cimarrón UruguayoOP
actually yes i want the metadata
for all routes with navbar
well but it should set on the page.tsx
ah ok
Cimarrón UruguayoOP
ah what did you change
Cimarrón UruguayoOP
import type { Metadata } from 'next'
import Navbar from '@/components/nav/Navbar'
export const metadata: Metadata = {
title: 'DigitalHippo',
description: 'A platform of high quality digital assets',
}
export default function RootWithNavbarLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<>
<Navbar />
<div className='flex-grow flex-1'>
{children}
</div>
</>
)
}app/(with-navbar)/layout.tsxtry restart dev server
Cimarrón UruguayoOP
app/layout.tsx// import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { cn } from '@/lib/utils'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
// export const metadata: Metadata = {
// title: 'DigitalHippo',
// description: 'A platform of high quality digital assets',
// }
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className="h-full">
<body className={cn(
inter.className,
"relative h-full font-sans antialiased"
)}>
<main className='relative flex flex-col min-h-screen'>
<div className='flex-grow flex-1'>
{children}
</div>
</main>
</body>
</html>
)
}ye i restarted
still doesn't work?
Cimarrón UruguayoOP
nope
is there a way to instead check the router for an unhandled route trigger
I don't think so
can you show the directory structure?
@Ray can you show the directory structure?
Cimarrón UruguayoOP
ye
am i having an infinite loop somewhere
well it should work
how about page.tsx?
or change
not-found.tsx to something like this instead of the ErrorPageimport Link from 'next/link'
export default function NotFound() {
return (
<div>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href="/">Return Home</Link>
</div>
)
}Cimarrón UruguayoOP
import Link from 'next/link'
import { ArrowDownToLine, CheckCircle, ShieldCheck } from 'lucide-react'
import { Button, buttonVariants } from '@/components/ui/button'
import MaxWidthWrapper from '@/components/standalone/MaxWidthWrapper'
import Perk from '@/components/standalone/Perk'
// omitted to save character count in discord
declare const perks: {
name: string;
Icon: LucideIcon;
description: string;
}[]
export default function Home() {
return (
<>
<MaxWidthWrapper>
<div className="py-20 mx-auto text-center flex flex-col items-center max-w-3xl">
<h1 className="text-8xl font-bold tracking-tight text-gray-900 md:text-6xl">
Your marketplace for high quality {' '}
<span className="text-blue-600">
digital assets
</span>
.
</h1>
<p className="mt-6 text-lg max-w-prose text-muted-foreground">
Welcome to DigitalHippo. Browse our platform of high quality assets verified by our team!
</p>
<div className="flex flex-col sm:flex-row gap-4 mt-6">
<Link href="/products" className={buttonVariants()}>Browse Popular</Link>
<Button variant="ghost">Our quality promise →</Button>
</div>
</div>
</MaxWidthWrapper>
<section className="border-t border-gray-200 bg-gray-50">
<MaxWidthWrapper className="py-20">
<div className="grid grid-cols-1 gap-y-12 sm:grid-cols-2 sm:gap-x-6 lg:grid-cols-3 lg:gap-x-8 lg:gap-y-0">
{
perks.map(({ name, Icon, description }) =>
<Perk key={name} name={name} Icon={Icon} description={description} />
)
}
</div>
</MaxWidthWrapper>
</section>
</>
)
}it looks fine
do you have middleware.ts?
Cimarrón UruguayoOP
nope
try different browser?
Cimarrón UruguayoOP
no luck 🥲
it can't be this hard
change
not-found.tsx to _not-found.tsxit keep redirecting you?
Cimarrón UruguayoOP
@Ray change `not-found.tsx` to `_not-found.tsx`
Cimarrón UruguayoOP
wait WTF
THAT WORKED
something wrong in not-found.tsx
@Cimarrón Uruguayo https://nextjs.org/docs/app/api-reference/file-conventions/not-found
Cimarrón UruguayoOP
docs lying
no, by adding a _ before it tell next to ignore it
Cimarrón UruguayoOP
can i just delete the not-found file lol
i just wanted the default error page anyways
yes then you don't have a custom 404 page lol
ah
Cimarrón UruguayoOP
ok i should have told you that from the beginnign 💀
my bad
ah wait
your question is omit rendering navbar component on 404
Cimarrón UruguayoOP
yeah
cos the problem was
and you want the default one?
Cimarrón UruguayoOP
layout.tsx will always render Navbar
so even if it was an error page, the navbar would still render
i just wanted to remove that from the error page
ah
@Ray and you want the default one?
Cimarrón UruguayoOP
yes
just delete
not-found.tsx is what you need then lolCimarrón UruguayoOP
thank you so much for the grouped route solution tho
you don't need route group for it
Cimarrón UruguayoOP
wait wh
if you don't have a
not-found.tsx, it will render the default oneCimarrón UruguayoOP
yes
but i need two different layout.tsx
ah ok
then you can keep the route group
Cimarrón UruguayoOP
yeah
thank you so much :)
np
Cimarrón UruguayoOP
ah yeah i was going to do that
thanks again