Issue with NavLink and activeClassName

I’m trying to implement a simple navigation using NavLink with className and activeClassName. I have a function which renders the links

const navItem = (item) => {
  const { index, title, link } = item
  return (
    <NavLink
      className={inactiveLink}
      activeClassName={activeLink}
      to={link}
      key={index}
    >
      {title}
    </NavLink>
  )
}

The activeLink and Inactive link are defined constants that contain tailwind strings

const activeLink =
  'inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-900 border-b-2 border-indigo-500'

const inactiveLink =
  'inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent hover:border-gray-300 hover:text-gray-700'

I have an array of link objects

 const navItems = [
    {
      index: 1,
      title: 'Home',
      link: routes.home(),
    },
    {
      index: 2,
      title: 'Sample',
      link: routes.sample(),
    },
    {
      index: 3,
      title: 'Page 1',
      link: routes.page1(),
    },
]

Finally, in my component I have

  {navItems.map((item) => {
     return navItem(item)
  })}

It always renders the items using the className and never uses the activeClassName.

I followed this example in the redwood documentation Active Link .

Any thoughts on what I’m doing wrong?

Hi.

To diagnose, if you remove the constants and in-line those tailwind styles in the NavLink attributes. Is the behavior the same?

Thanks for the suggestion!

I did remove the constants and still got the same results. I even tried just building the NavLink in the main return section of the component and still got the same behavior. It always just uses the className attribute and never seems to use the activeClassName attribute, even when the URL matches the route.

Can you share your Routes file please? And could you also please run console.log('navItems', navItems) somewhere in your code and show us the output?

Thanks!

What do the location urls look like?

You they have any query string params or extraneous info apart from the route and any param?

The params do need to match to know if the route is active or not

Hi Tobbe,
Here is the navItems printed in the console

{index: 1, title: 'Home', link: '/'}
{index: 2, title: 'Sample', link: '/sample'}
{index: 3, title: 'Page 1', link: '/page1'}
{index: 4, title: 'Page 2', link: '/page2'}
{index: 5, title: 'Page 3', link: '/page3'}

And here is my Routes File

 <Router>
      <Set wrap={TopnavLayout}>
        <Route path="/" page={HomePage} name="home" />
        <Route path="/sample" page={SamplePage} name="sample" />
        <Route path="/page3" page={Page3Page} name="page3" />
        <Route path="/page2" page={Page2Page} name="page2" />
        <Route path="/page1" page={Page1Page} name="page1" />
        <Route path="/login" page={LoginPage} name="login" />
        <Route path="/signup" page={SignupPage} name="signup" />
        <Route path="/forgot-password" page={ForgotPasswordPage} name="forgotPassword" />
        <Route path="/reset-password" page={ResetPasswordPage} name="resetPassword" />
      </Set>

      <Route notfound page={NotFoundPage} />
    </Router>

I even tried just adding the NavLink directly and it didn’t work.

<NavLink
      to={routes.home()}
      activeClassName='inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-900 border-b-2 border-indigo-500'
      className='inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent hover:border-gray-300 hover:text-gray-700'>
      Home
</NavLink>

The links work fine, it’s just the underline of the active link that is not working.

I’ve tried it in Safari (16.2) and Chrome (Version 109.0.5414.119 (Official Build) (arm64)) and I get the same results.

And if it helps this this is what I get from yarn rw info

 System:
    OS: macOS 13.1
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 16.13.0 - /private/var/folders/kz/sy0k3fv16g5d4hgcvcc1xp7w0000gn/T/xfs-39c3a08c/node
    Yarn: 3.3.0 - /private/var/folders/kz/sy0k3fv16g5d4hgcvcc1xp7w0000gn/T/xfs-39c3a08c/yarn
  Databases:
    SQLite: 3.39.5 - /usr/bin/sqlite3
  Browsers:
    Chrome: 109.0.5414.119
    Safari: 16.2
  npmPackages:
    @redwoodjs/core: 3.8.0 => 3.8.0 

The only packages I’ve installed are

  • tailwindcss (yarn rw setup ui tailwindcss)
  • @headlessui/react@1.6.1
  • @heroicons/react@2.0.14

I’m really enjoying learning this product, and I already tell its going to speed development significantly.

Hi dthyresson,

If you look at the reply I just sent to Tobbe, I have all the info. The links have no query params on them, just basic links. The links work, I just don’t get the update for the active link.

I do appreciate the help! It’s be fun learning redwood, and I’m excited to use it on some future endeavors.

@Tobbe , @dthyresson
I was able to develop a workaround. I simply changed my navItem function to this

const navItem = (item, pathname) => {
  const { index, title, link } = item

  return (
    <Link
      className={pathname === link ? activeLink : inactiveLink}
      to={link}
      key={index}
    >
      {title}
    </Link>
  )
}

Then in my main layout routine I simply use the useLocation() hook to get the current url and pass it to the navItem function as a prop. This gives me the desired results.

Thanks for all the details. Great that you found a workaround, but I’m definitely still interested in understanding exactly what’s going on here :slight_smile: Nothing jumps out at me immediately though. I’ll think about it some more