Next.js Discord

Discord Forum

What is the most idiomatic way to show or hide something based on request pathname in NextJS 14?

Unanswered
troop4christ posted this in #help-forum
Open in Discord
I have components that I wan't to show up in my layout.js for all requested paths except for say /foo and /bar/** ..

I'm trying to use the middleware.js x-pathname header w/ next/headers hack.. cough... workaround.

// /middleware.js
  const { pathname } = req.nextUrl
  console.log(`pathname =>`, pathname)
  // This is a workaround to pass the pathname to SSR pages
  const requestHeaders = new Headers(req.headers)
  requestHeaders.set('x-pathname', pathname)


// layout.js
import {headers} from 'next/headers'
const getReqPathname = async () => {
  const headersList = headers()
  console.dir([...headersList.entries()], { depth: 3, colors: true })
  return headersList.get('x-pathname')
}

//JSX
const pathname = getReqPathname()
{ !pathname.startsWith('/foo') : <Component /> } 


But I'm seeing a behavior where a hidden component for a given pathname, if the user navigates to a different pathname, will stay hidden, even if it's supposed to show.. and vice versa..

It works fine on page load.. just not transitioning from one route/path to another.

I need a solution that will allow for SSR pages to still be renderable on the server and won't require client-side code like usePathname or anything like that.

4 Replies

@troop4christ I have components that I wan't to show up in my `layout.js` for all requested paths except for say `/foo` and `/bar/**` .. I'm trying to use the `middleware.js` `x-pathname` header w/ `next/headers` hack.. *cough*... workaround. javascript // /middleware.js const { pathname } = req.nextUrl console.log(`pathname =>`, pathname) // This is a workaround to pass the pathname to SSR pages const requestHeaders = new Headers(req.headers) requestHeaders.set('x-pathname', pathname) javascript // layout.js import {headers} from 'next/headers' const getReqPathname = async () => { const headersList = headers() console.dir([...headersList.entries()], { depth: 3, colors: true }) return headersList.get('x-pathname') } //JSX const pathname = getReqPathname() { !pathname.startsWith('/foo') : <Component /> } But I'm seeing a behavior where a hidden component for a given pathname, if the user navigates to a different pathname, will _stay_ hidden, even if it's supposed to show.. and vice versa.. It works fine on page load.. just not transitioning from one route/path to another. I need a solution that will allow for SSR pages to still be renderable on the server and won't require client-side code like `usePathname` or anything like that.
Britannia Petite
I think Im having a very similar problem where I'm trying to conditionally load layouts based on the path they are on and its just fucking turbo aids. Correct me if I'm wrong but this should just straight up not be this hard to do, it's like an impossible feat just to properly load certain elements or element attributes in
Maybe you can try declaring your layout as a client component and then importing the async stuff somewhere else, I dont think that works though I genuinely have no idea
American black bear
usePathname then if pathname === something return null for elements you dont want
@American black bear that alone doesn't work for SSR pages/routes. It causes layout shift for SSR pages.

@Britannia Petite I ultimately had to leverage an initPathname prop into the components that I wanted to show/hide based on pathname. That prop would be fed by the x-pathname hack mentioned above.

Inside of those components, set an initial show state to that initPathname prop, but then also leverage usePathname, and then have a useEffect that looks at the resultant client-side pathname, and update the show state accordingly whenever the route changed in the browser.