Get pathname on 404 pages (server component)?
Unanswered
English Setter posted this in #help-forum
English SetterOP
Is there a way to get the "not found" pathname on a server side 404 page
The constraint is statically generated catch all route
I tried a workaround to put the pathname in a custom header in the middleware, but the
The use case being a smarter 404 with more context and CTAs than an "oops"
Thank you very much!
The constraint is statically generated catch all route
export const dynamic = 'force-static'I tried a workaround to put the pathname in a custom header in the middleware, but the
force-static strips the headers at runtimeThe use case being a smarter 404 with more context and CTAs than an "oops"
Thank you very much!
13 Replies
@English Setter Is there a way to get the "not found" pathname on a server side 404 page
The constraint is statically generated catch all route `export const dynamic = 'force-static'`
I tried a workaround to put the pathname in a custom header in the middleware, but the `force-static` strips the headers at runtime
The use case being a smarter 404 with more context and CTAs than an "oops"
Thank you very much!
you can simply use
usePathname in the app/not-found.tsxEnglish SetterOP
I want it to be a server component for some filesystem access
not-found.tsx is a server comonent https://nextjs.org/docs/app/api-reference/file-conventions/not-found#data-fetching
@English Setter I want it to be a server component for some filesystem access
American Crow
Split in two components and import the stuff that needs client interaction
not-found.tsx (server)
not-found-client.tsx (client)
not-found.tsx (server)
import NotFoundClient from "@/app/not-found-client";
export default function Custom404() {
return (
<div className="flex flex-col items-center justify-center h-screen">
<h1 className="text-4xl font-bold">404 - Page Not Found</h1>
<NotFoundClient />
<p className="text-lg">Sorry, the page you are looking for does not exist.</p>
</div>
)
}not-found-client.tsx (client)
"use client"
import { usePathname } from "next/navigation";
export default function NotFoundClient() {
const path = usePathname()
return (
<h2 className="text-lg font-bold tracking-tight"> Path "{path}" is not valid </h2>
)
}English SetterOP
Thanks for the suggestion @American Crow , but I need the pathname to generate a sidebar that has to be a server component for fs access
I'm not sure if a client component can render a server component? 🤔
I'm not sure if a client component can render a server component? 🤔
American Crow
a sidebar in a 404 ? or is this a separate use case
@English Setter Thanks for the suggestion <@240974567730970625> , but I need the pathname to generate a sidebar that has to be a server component for fs access
I'm not sure if a client component can render a server component? 🤔
American Crow
I dont know what you try to achieve exactly within the sidebar. If you just want to do for example active links. You can do something like this:
sidebar (server)
sidebar-links (client)
sidebar (server)
import SidebarLink from "@/app/sidebar/sidebar-link"
// Server
export default function Sidebar() {
return (
<div className="flex bg-orange-300 h-24 items-center px-4 space-x-8">
<SidebarLink href="/">Home</SidebarLink>
<SidebarLink href="/1">1</SidebarLink>
<SidebarLink href="/2">2</SidebarLink>
<SidebarLink href="/sidebar">3</SidebarLink>
</div>
)
}sidebar-links (client)
"use client"
import { cn } from "@/lib/utils";
import Link from "next/link";
import { usePathname } from "next/navigation";
export default function SidebarLink({href, children}) {
const path = usePathname()
const linkIsActive = path === href
return (
<Link href={href} className={cn("px-4 py-2", linkIsActive ? "bg-blue-300" : "bg-blue-100")}> {children} </Link>
)
}English SetterOP
I'm in a situation where the
SidebarLinks themselves are built from reading a directory of mdx files @American Crow@English Setter I'm in a situation where the `SidebarLink`s themselves are built from reading a directory of mdx files <@240974567730970625>
American Crow
Which you read server side, no? Can you not just load them in the Server Sidebar map through them and create a SidebarLink for each? Sorry if a don't understand the use case
English SetterOP
Sorry my explanation wasn't very clear, I tried to simplify.
We have different kinds of sidebars for different paths, so the server kinda needs to be aware of the pathname
I tried to workaround it, but in the I keep coming back to "I need a server side
We have different kinds of sidebars for different paths, so the server kinda needs to be aware of the pathname
I tried to workaround it, but in the I keep coming back to "I need a server side
usePathname()"American Crow
Yea there is no direct server side usePathname(). Best you can do is look at athe file directory and if its a dynamic segment read the {params}. So combosing it by hand kind of
@English Setter Sorry my explanation wasn't very clear, I tried to simplify.
We have different kinds of sidebars for different paths, so the server kinda needs to be aware of the pathname
I tried to workaround it, but in the I keep coming back to "I need a server side `usePathname()`"
American Crow
Btw this would still work with the approach from above:
Last try i'll shut up now 😆
import SidebarLink from "@/app/sidebar/sidebar-link"
const fakeMdxPaths = [
{
id: 1,
path: "/apple",
},
{
id: 2,
path: "/banana",
},
{
id: 3,
path: "/cherry",
},
]
// Server
export default function SidebarLoader() {
// Load path from mdx file
const mdxPath = fakeMdxPaths[0]
let SidebarComponent = DefaultSidebar
if (mdxPath.path.startsWith("/a")) {
SidebarComponent = AppleSidebar
} else if (mdxPath.path.startsWith("/b")) {
SidebarComponent = BananaSidebar
}
return <SidebarComponent />
}
export function DefaultSidebar() {
return (
<div className="bg-gray-300">
<SidebarLink href="/apple">Apple</SidebarLink>
<SidebarLink href="/banana">Banana</SidebarLink>
<SidebarLink href="/cherry">Cherry</SidebarLink>
</div>
)
}
export function AppleSidebar() {
return (
<div className="bg-red-500">
<SidebarLink href="/apple">Apple</SidebarLink>
<SidebarLink href="/sidebar">Sidebar</SidebarLink>
<SidebarLink href="/cherry">Cherry</SidebarLink>
</div>
)
}
export function BananaSidebar() {
return (
<div className="bg-yellow-300">
<SidebarLink href="/apple">Apple</SidebarLink>
</div>
)
}Last try i'll shut up now 😆

English SetterOP
I really appreciate the effort, but my use case is much more complicated, and I also need some breadcrumbs to be generated server side