Not too familiar with react router, but I need the functionality of the NavLink to set the active class on the parent li
element, and not the a
ele
Check this one
class LiNavLink extends React.Component<NavLinkProps> {
render() {
return (
<Route exact={this.props.exact} path={this.props.to.toString()}>
{
({ match }) =>
<li className={match ? 'active' : undefined}>
<Link to={this.props.to} >
{this.props.children}
</Link>
</li>
}
</Route>
);
}
}
I found that by using CSS you can make the active link expand to fill up it's parent <li>
element by setting display:block;
in the active class.
For example if our link was:
<li>
<NavLink to="/overview" className=styles.sideLink activeClassName=styles.sideLinkSelected>
Overview
</NavLink>
</li>
then our CSS would be:
&__sideLinkSelected
{
background-color: blue;
display:block;
}
I am just starting with the react, so not sure if this is the best practices, but after going through router v4 docs, I used withRouter props -> location.pathname and compared it to my route.
Here is the Navigation.js:
import React from 'react';
import { withRouter } from 'react-router-dom';
import NavLink from '../General/NavLink';
const activeClass = (path, link) => {
if (path === link) {
return true;
}
return false;
};
const Navigation = props => {
const { location } = props;
return (
<ul className="menu menu--main nano-content">
<NavLink
to="/"
parentClass={
activeClass(location.pathname, '/')
? 'menu__item menu__item--active'
: 'menu__item'
}
linkClass="menu__link effect effect--waves"
>
Dashboard
</NavLink>
<NavLink
to="/users"
parentClass={
activeClass(location.pathname, '/users')
? 'menu__item menu__item--active'
: 'menu__item'
}
linkClass="menu__link effect effect--waves"
>
Users
</NavLink>
<NavLink
to="/projects"
parentClass={
activeClass(location.pathname, '/projects')
? 'menu__item menu__item--active'
: 'menu__item'
}
linkClass="menu__link effect effect--waves"
>
Projects
</NavLink>
<NavLink
href="http://google.com"
parentClass="menu__item"
linkClass="menu__link effect effect--waves"
>
Google
</NavLink>
</ul>
);
};
export default withRouter(Navigation);
From there you have parent and child classes that you can use on child component.
In v4 after lots of tries I did.
Here my working code.
import React, { Component } from "react";
import logo from "../../logo.svg";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
class Navbar extends Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
state = {};
getNavLinkClass = path => {
return this.props.location.pathname === path
? "nav-item active"
: "nav-item";
};
render() {
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<Link className="navbar-brand" to="/">
<img
src={logo}
width="30"
height="30"
className="d-inline-block align-top"
alt=""
/>
Utility
</Link>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon" />
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className={this.getNavLinkClass("/")}>
<Link className="nav-link" to="/">
Home
</Link>
</li>
<li className={this.getNavLinkClass("/age-counter")}>
<Link className="nav-link" to="/age-counter">
Age Counter
</Link>
</li>
</ul>
</div>
</nav>
);
}
}
export default withRouter(Navbar);
Demo working Code Sandbox