Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

activeClassName in react router is highlighting two NavLinks at the same time

I'm learning React Router and following this tutorial Everything is clear and working as instructed (thank you author) except an issue that highlights the active NavLink.

Take a look at the css file and note the .current class:

nav ul {
  list-style: none;
  display: flex;
  background-color: black;
  margin-bottom: 20px;
}

nav ul li {
  padding: 20px;
}

nav ul li a {
  color: white;
  text-decoration: none;
}

.current {
  border-bottom: 4px solid white;
}

When I load the app, Home link in the navi is highlighted with a the white bottom border line but it stays highlighted even when I click on the "about" link or the "Contact" link. I followed everything step by step but this one issue I can't figure out.

After reading the react documentaton about the NavLink and many tutorials online, still, don't know how to fix it.

Here is when I click on the about link enter image description here

Here is when I click on Contact link enter image description here

This is how the tutorial routes example

<nav>
    <ul>
      <li><NavLink exact activeClassName="current" to='/'>Home</NavLink></li>
      <li><NavLink exact activeClassName="current" to='/about'>About</NavLink></li>
      <li><NavLink exact activeClassName="current" to='/contact'>Contact</NavLink></li>
    </ul>
  </nav>

Notice how the Home link stays with the active white line under it despite the fact that it is not the active link anymore.

Adding activeClassName="current" suppose to highlight the current view with white underline but the home link stays highlighted with the white underline.

So, to all of you out there with years of experience, please help.

Here is My app.js

    import React, { Component } from 'react';
import './App.css';
import Main from './components/main';
import Navigation from './components/navigation';




class App extends Component {
  render() {
    return (
        <div>
            <h1> React Router </h1>;
            <h5>  import 'BrowserRouter' from 'react-router-dom' in Appjs</h5>
            <hr></hr>

            <Navigation />

            <Main />
            </div>

    );
  }
}

 export default App;

Here is my index.js

    import React from 'react';
import ReactDOM from 'react-dom';
//Add browserrouter to use it in your app
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

//this router example is from this site 
//https://blog.pusher.com/getting-started-with-react-router-v4/
/*
You can only pass a single child element to a Router,
so it is necessary to create a root component
that renders the rest of your application and
then pass that in as the child of the Router.
*/
ReactDOM.render((
    <BrowserRouter>
        <App />
    </BrowserRouter>
), document.getElementById('root')); 

Here is my main.js

 import React, { Component } from 'react';
import { NavLink, Switch, Route } from 'react-router-dom';
import Home from './home';
import About from './about'
import Contact from './contact'

class Main extends Component {
    render() {
        return (
            <div>
                <p> My main component </p>
                <Switch>
                    <Route exact={true}  path='/' component={Home}></Route>
                    <Route   path='/about' component={About}></Route>
                    <Route   path='/contact' component={Contact}></Route>
                    </Switch>
            </div>
        );
    }
}

export default Main;

And finally here is my navigation.js

    import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

class Navigation extends Component {
    render() {
        return (
            <div>
            <p> My Navigation component </p>
            <nav>
                <ul>
                    <li><NavLink to='/'> Home </NavLink> </li>
                    <li><NavLink to='/about'> About </NavLink> </li>
                    <li><NavLink to='/contact'> Contact </NavLink> </li>
                </ul>
            </nav>
                </div>
        );
    }
}

export default Navigation;
like image 281
Marco Avatar asked Oct 26 '18 17:10

Marco


2 Answers

The Navlink also needs an exact on it... Change to this:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

class Navigation extends Component {
  render() {
    return (
      <div>
        <p> My Navigation component </p>
        <nav>
          <ul>
            <li><NavLink to='/' activeClassName="current" exact={true}> Home </NavLink> </li>
            <li><NavLink to='/about' activeClassName="current"> About </NavLink> </li>
            <li><NavLink to='/contact' activeClassName="current"> Contact </NavLink> </li>
          </ul>
        </nav>
      </div>
    );
  }
}

export default Navigation;
like image 156
SakoBu Avatar answered Oct 24 '22 03:10

SakoBu


You should add the exact property to your root("") Route, otherwise, it will match every route starting with "", React Router exact

eg:

<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />

Update:

Also changing the order will have same effect without exact property

<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
<Route path="/" component={Home} />

in side a router switch it will go to the first matching route, if we add a route with path / at the beginning it will always render the component in the path, it is better avoid exact fix with order

like image 28
Hafeez Hamza Avatar answered Oct 24 '22 05:10

Hafeez Hamza