Next.js Discord

Discord Forum

usePathname links correctly but shows different link as active.

Answered
Northeast Congo Lion posted this in #help-forum
Open in Discord
Northeast Congo LionOP
'use client'
 
import { usePathname } from 'next/navigation'
import Link from 'next/link'
 
export function Links() {
  const pathname = usePathname()
 
  return (
    <nav>
      <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
        Home
      </Link>
 
      <Link
        className={`link ${pathname === '/about' ? 'active' : ''}`}
        href="/about"
      >
        About
      </Link>
    </nav>
  )
}

As I've noted above, this hook is working correctly, but is inverting the active link. I my case, Navigating to the Home page works fine, but it shows About as active, and navigating to About works, but shows Home as active. It's very puzzling. Any ideas?
Answered by ᴉuɐpɹɐɐ
pathname === "/" ? "bg-[#FFEE32]" : ""

pathname === "/" && "bg-[#FFEE32]"
View full answer

58 Replies

Northeast Congo LionOP
Here's a snippet of the code. The background hover works as wanted, as does the navigation. The issue is, navigating to Home gives the active background to Oracle, and navigating to Oracle gives the active background to Home.

 const pathname = usePathname();
  return (
    <nav className="font-mono text-4xl p-5 border-b border-[#FFEE32]">
      <ul className="flex flex-row flex-wrap justify-end">
        <li
          className={`mr-auto cursor-pointer rounded-lg p-1 hover:bg-[#33353320] ${
            pathname === "/home" ? "active" : "bg-[#FFEE32]"
          }`}
        >
          <Link href="/home">Home</Link>
        </li>
        <li
          className={`mr-auto cursor-pointer rounded-lg p-1 hover:bg-[#33353320] ${
            pathname === "/oracle" ? "active" : "bg-[#FFEE32]"
          }`}
        >
it makes me feel like this is a bug of the active class since pathname seems to be correct. Could you display the pathname value somehow, like <Link href="/home">{pathname}</Link>, to see if it's correct?
Could be wrong but i think i read somewhere that doing conditionals directly in className with tailwind classes dont work well. Or maybe it just had to do with using conditionals inside arbitrary tailwind classes
no, doing conditionals directly in className works well.
`bg-${pathname === "/" ? "red" : "blue"}`

doesn't work, but
pathname === "/" ? "bg-red" : "bg-blue"

works well.
Yes but does it work well with templates like he is doing?
yes
I use the second type aswell, but its mostly the entire string replacement
their code looks fully correct, thats what made me think this is a css issue of the .active class
@Northeast Congo Lion This shows /home in the navbar.
does it show /home when you are in /home and /oracle when you are in /oracle? in other words, does it show the current pathname correctly?
Northeast Congo LionOP
Curious....Home makes them both Home, and Oracle makes them both Oracle...
They're sharing a link, but they navigate correctly, in that the correct page shows.
I have both routes going to the Home/page.tsx and then to page.tsx, then layout.tsx. Perhaps the issue lives there...
That's not it either. When I move Oracle out of home, it still shows / / in the navbar, with both showing the Active backround.
ok i am confused on what's going on. could you make a simple reproduction repository that i can look at, pull to my computer and test it?
Northeast Congo LionOP
I've never done that before. This also isn't up on Git Hub. Any other way?
well without it i have no idea what's going on
Northeast Congo LionOP
What other pages can I show you?
@Northeast Congo Lion I have both routes going to the Home/page.tsx and then to page.tsx, then layout.tsx. Perhaps the issue lives there...
For starters i dont get what you mean by this. Also show the screenshot of your folder structure
Northeast Congo LionOP
This is the root layout;
tsx export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${inter.variable} ${caveat.variable}`}>
        <div className="bg-[#D6D6D6] m-2 md:mx-4 lg:mx-8 xl:mx-52 max-w-screen-xl rounded-lg">
          <Header />
          {children}
          <Footer />
        </div>
      </body>
    </html>
  );
}
import Home from "./home/page";
export default function Index() {
  return (
    <main>
      <Home />
    </main>
  );
}
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const Header: React.FC = () => {
  const pathname = usePathname();
  return (
    <nav className="font-mono text-4xl p-5 border-b border-[#FFEE32]">
      <ul className="flex flex-row flex-wrap justify-end">
        <li
          className={`mr-auto cursor-pointer rounded-lg p-1 hover:bg-[#33353320] ${
            pathname === "/home" ? "active" : "bg-[#FFEE32]"
          }`}
        >
          <Link href="/home">Home</Link>
        </li>
        <li
          className={`mr-auto cursor-pointer rounded-lg p-1 hover:bg-[#33353320] ${
            pathname === "/oracle" ? "active" : "bg-[#FFEE32]"
          }`}
        >
          <Link href="/oracle">Oracle</Link>
        </li>
        <li className="text-center cursor-pointer rounded-lg p-1 hover:bg-[#33353320]">
          <a href="/history">History</a>
        </li>
        <li className="text-center cursor-pointer rounded-lg p-1 hover:bg-[#33353320]">
          <a href="/hexagrams">Hexagrams</a>
        </li>
      </ul>
    </nav>
  );
};

export default Header;
Sorry if I've made this ugly and complicated...
Here's the Home page. I have it populated because I didn't know how else to have everything visible/scrollable from Home.
"use client";
import Hero from "./hero";
import Oracle from "../oracle/page";

const Home = () => {
  return (
    <>
      <Hero />
      <Oracle />
    </>
  );
};
export default Home;
Northeast Congo LionOP
I'm pretty sure the problem is my routing and the answer lies here; 'When a layout.js and page.js file are defined in the same folder, the layout will wrap the page.'
From reading all this i am 100% sure you dont know how routing in nextjs works.
usePathname returns everything after your "url host" meaning:

"http://localhost:3000/home" will return "/home" and "http://localhost:3000" will return "/"
@Clown From reading all this i am 100% sure you dont know how routing in nextjs works.
Northeast Congo LionOP
You are 100% correct. I didn't/don't know how to be able to scroll every page and have the pages routable. For example, when Oracle/page.tsx goes directly to page.tsx, no other page is visible and I would have to use the navbar or browser back. I want both options. This is my first try with Next.js and, yes, I'm pretty baffled by the routing.
Northeast Congo LionOP
So, no actual help then?
@Northeast Congo Lion So, no actual help then?
If you have now understood the actual problem then your question should be solved.

If there is something you want to do and you dont know if its possible or not with nextjs, then you should open up a separate question and ask for that specific thing, cause i currently dont get what you wanted to achieve. usePathname is working as expected as it is now.
Northeast Congo LionOP
It's not. Nothing has changed. Home sets Oracle to active and Oracle sets Home to active. I'm really unsure how to fix it, otherwise I surely would have.
@ᴉuɐpɹɐɐ do you have a demo
Northeast Congo LionOP
No, not yet. I'm trying to get a little further along before I go to Git Hub. I'm sure the problem is my routing, but I can't figure it out yet.
Northeast Congo LionOP
I'm broken....
I've fixed the routing to remove redunduncies but still - when I click home, it navigates to Home correctly, but Oracle has the pathname '/'. When I click Oracle, it's navigated to correctly but Home gets the active background.
I'm at a complete loss...
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const Header: React.FC = () => {

const pathname = usePathname();
  return (
    <nav className="font-mono text-4xl p-5 border-b border-[#FFEE32]">
      <ul className="flex flex-row flex-wrap justify-end">
        <li
          className={`mr-auto cursor-pointer rounded-lg p-1 hover:bg-[#33353320] ${
            pathname === "/" ? "active" : "bg-[#FFEE32]"
          }`}
        >
          <Link href="/">Home</Link>
        </li>
        <li className="text-center cursor-pointer rounded-lg p-1 hover:bg-[#33353320]">
          <Link href="/oracle">Oracle</Link>
        </li>
        <li className="text-center cursor-pointer rounded-lg p-1 hover:bg-[#33353320]">
          <a href="/history">History</a>
        </li>
        <li className="text-center cursor-pointer rounded-lg p-1 hover:bg-[#33353320]">
          <a href="/hexagrams">Hexagrams</a>
        </li>
      </ul>
    </nav>
  );
};

export default Header;
This is page.tsx
// import Home from "./home/page";
import Hero from "./components/hero";
import Oracle from "./oracle/page";
export default function Page() {
  return (
    <main>
      <Hero />
      <Oracle />
    </main>
  );
}

and here's my routing
do you have a demo?
@ᴉuɐpɹɐɐ do you have a demo?
Northeast Congo LionOP
I just got it going in codesandbox, but all manner of funkiness is going down.
https://codesandbox.io/p/devbox/i-ching-too-wgml2l
@joulev could you make a [minimal reproduction repository](https://l.joulev.dev/mrr)?
Northeast Congo LionOP
Hi. I've put this code in codesandbox. If you could help me, I'd be thrilled. https://codesandbox.io/p/devbox/i-ching-too-wgml2l?file=%2Fapp%2Fcomponents%2Fheader.tsx%3A17%2C16
what kind of behavior are you expecting?
Northeast Congo LionOP
As it is, it navigates correctly, but clicking Home doesn't add the active background, however, clicking Oracle, for example DOES add the active background to Home. Further, when testing with {pathname}, any link clicked changes every pathname. For example, clicking Oracle makes every pathname /oracle.
pathname === "/" ? "active" : "bg-[#FFEE32]"
This means that when current pathname is at / then write the active class.
And if the current pathname is not at / then write the bg-[#FFEE32] class.

I am in /oracle and the "HOME" text lights up with #FFEE32

its working perfectly fine
however, clicking Oracle, for example DOES add the active background to Home
It does not add the active background. It adds the bg-[#ffe32] background.
I checked your .css files there is no declaration of active and active is not a valid Tailwindcss class, therefore it will not show anything
Northeast Congo LionOP
Then I've reversed things. I want to click on Home, and have Home get a yellow background.
then reverse the ternary operator
Northeast Congo LionOP
pathname === "/" ? "active" : "bg-[#FFEE32]"

what will this look like if I want Home to get the background. I'm sorry, I'm terribly turned around at this point.
pathname === "/" ? "bg-[#FFEE32]" : ""

pathname === "/" && "bg-[#FFEE32]"
Answer
any of these two
Northeast Congo LionOP
I did that just before you wrote. Essentially, I'm a fucking idiot. Thank you very much.
no worries, it happens
idk why