Home > database >  The "isActive" prop for React's NavLink isn't working
The "isActive" prop for React's NavLink isn't working

Time:10-20

I'm making a little ticker animation for my navbar but for some reason, the ticker doesn't move when I click on a NavLink. At first, I thought it was a problem with the CSS file but that seems to be working fine. I then tried using an older version of react-router-dom but that also didn't seem to work. Some help would be appreciated.

As you can see, the 'active-nav' class is supposed to change to any NavLink that is Active & the rest are left with empty quotation marks.

Navbar.jsx:

import {Link, NavLink} from 'react-router-dom'
import {links} from '../data'
import {GoThreeBars} from 'react-icons/go'
import Logo from '../images/logo.png'
import "./navbar.css"
const Navbar = () => {
  return (
    <nav> 
        
        <div className='container nav__container'>
            <Link to="/" className='logo'>
                <img src={Logo} alt="Nav Logo"/>
            </Link>
            <ul className="nav__links">
                {
                    links.map(({name, path}, index) => {
                        return (
                            <li>
                                <NavLink to={path} className={({isActive}) => isActive ? 'active-nav' : ''}>{name}</NavLink>
                            </li>
                        )
                    })
                }
            </ul>
            <button className="nav__toggle-btn">
                <GoThreeBars />
            </button>
        </div>
    </nav>
    
  )
}

export default Navbar

  • Here you can see that most of the functionality is in the CSS

navbar.css:

nav {
    height: 5rem;
    width: 100vw;
    background: var(--color-primary);
    display: grid;
    place-items: center;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 99;
}

/* only shows on medium and small screens */

.nav__toggle-btn {
    display: none;
}

.nav__container {
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    width: 1920px;
}

.logo {
    width: 7rem;
    margin-right: 400px;
}

.nav__links {
    display: flex;
    gap: 3.5rem;
}

.nav__links a {
    transition: var(--transition);
}

.nav__links a:hover {
    color: var(--color--secondary);
}

.active-nav {
    position: relative;
}

.nav__links::after {
    content: '';
    display: block;
    width: 1.2rem;
    height: 1.2rem;
    background: var(--color-primary);
    position: absolute;
    left: calc(50% - 0.6rem);
    transform: rotate(45deg);
    margin-top: 2.7rem;
}

package.json

{
  "name": "reactappblue",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-icons": "^4.6.0",
    "react-router-dom": "^6.3.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

app.js:

import {BrowserRouter, Routes, Route} from 'react-router-dom'

import Home from './pages/home/Home'
import About from './pages/about/About'
import Contact from './pages/contact/Contact'
import Gallery from './pages/gallery/Gallery'
import Plans from './pages/plans/Plans'
import Trainers from './pages/trainers/Trainers'
import NotFound from './pages/notfound/Notfound'
import Navbar from './components/Navbar'
import {BrowserRouter as Router} from 'react-router-dom'


const App = () => {
  return (
    <BrowserRouter>
      <Navbar />
      <Routes>
        <Route index element={<Home/>} />
        <Route path="about" element={<About/>} />
        <Route path="contact" element={<Contact/>} />
        <Route path="gallery" element={<Gallery/>} />
        <Route path="plans" element={<Plans/>} />
        <Route path="trainers" element={<Trainers/>} />
        <Route path="*" element={<NotFound/>} />
      </Routes>
    </BrowserRouter>
  )
}

export default App

CodePudding user response:

It's rather hard to exactly reproduce your problem since you are missing some relevant information in your question. I made some assumptions:

  • Your package.json would have been valuable since it contains the versions of the packages you're using, I used "react": "18.2.0" and "react-router-dom": "6.4.2"
  • I wrapped the Navbar in a react-router-dom BrowserRouter in the parent component like this:
import Navbar from './Navbar.jsx';
import {BrowserRouter as Router} from 'react-router-dom'

function App() {
  return (
    <Router>
      <div className="App">
        <Navbar/>
      </div>
    </Router>
  );
}

Doing so, the class name was set properly for me. I didn't have to change any parts of the code you provided.

I hope this already helps, if not, please provide the versions of the packages you're using and how the <Navbar /> component is instantiated in its parent component(s).

CodePudding user response:

You can simply use activeClassName prop.

<NavLink to={path} activeClassName="active-nav">{name}</NavLink>

If you are using className you don't need to destructure {isActive}, simply use

<NavLink
  to={path}
  className={isActive => isActive ? 'active-nav' : ''}
>
{name}
<NavLink/>
  • Related