How can I style active Link in react-router v4?
In react-router v3 we had activeStyle and activeClassName to style active Link
we could do something like this
<div id="tags-container">
{tags.map(t =>
<Link
className="tags"
activeStyle={{ color: 'red' }}
to={t.path}
>
{t.title}
</Link>
)}
</div>
I wanna know how can I do same thing in v4?
Solution 1:
Use NavLink instead Link. Its not documented, but its work as you expect. https://github.com/ReactTraining/react-router/issues/4318
UPDATE 17.05.2017:
https://reacttraining.com/react-router/web/api/NavLink
Solution 2:
You can do it with NavLink
in react-router
v4
<div id="tags-container">
{tags.map(t =>
<NavLink
className="tags"
activeStyle={{ color: 'red' }}
to={t.path}
>
{t.title}
</NavLink>
)}
</div>
Solution 3:
If you are encountering an issue where your Nav menu works except it's not updating properly when you click links and the route changes, but it works fine if you press F5, you can do this:
This is probably occurring because you are using Redux which has a shouldComponentUpdate
Lifecycle method on its connect
function. You probably have your Nav component wrapped in connect
. This is all good. shouldComponentUpdate
is what is ruining your life.
To fix, just bring the router into your mapStateToProps
function:
// This lets shouldComponentUpdate know that the route changed,
// which allows the Nav to re-render properly when the route changes, woot!
const mapStateToProps = (state) => {
return {
router: state.router,
}
}
// or, if you prefer pro style destructure shorthand:
const mapStateToProps = ({ router }) => ({ router })
If you aren't quite sure where state.router
comes from, it comes from the file you combine your reducers in, and you will see something like this:
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'
import authReducer from './components/auth/auth_reducer'
export default combineReducers({
router: routerReducer,
auth: authReducer,
})
Here is some HTML and CSS for a pretty baller Nav Link:
HTML
<ul id="Nav_menu">
<li>
<NavLink
to="/home"
className="Nav_link"
activeClassName="activeRoute"
activeStyle={{ color: 'teal' }}
>
HOME
</NavLink>
</li>
<li>
<NavLink
to="/products"
className="Nav_link"
activeClassName="activeRoute"
activeStyle={{ color: 'teal' }}
>
PRODUCTS
</NavLink>
</li>
</ul>
NOTE: If you are linking to "/"
, put exact
prop on NavLink.
CSS
#Nav_menu {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
list-style-type: none;
margin: 0;
padding: 0;
}
.Nav_link:link {
color: #fff;
font-size: 1.6rem;
line-height: 1.6rem;
text-decoration: none;
}
.Nav_link:visited {
color: #fff;
}
.Nav_link:hover {
color: yellow;
}
.Nav_link:active {
color: teal;
}
.activeRoute {
background-color: yellow;
border-bottom: 0.4rem solid teal;
cursor: not-allowed;
}
Notice activeStyle
in the HTML markup. This was the only way I could change the color of the text on the active route/link. It didn't work when I put color: teal;
in the activeRoute
CSS Class. Open this in another tab: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/NavLink.md
If you don't know why I used rem
instead of px
. This is a great opportunity for you to research web accessibility and base font-size: 10px;
.
Stay fit and have fun.
Solution 4:
Expanding on @agm1984's answer:
The solution of NavLinks is not updating styles correctly, which was using routerReducer
from react-router-redux
, has not worked for me. Instead, I found out that the issue was that connect
wrapper uses shouldComponentUpdate
and prevented rerendering of the component containing NavLinks.
Correct solution in my situation was to pass options object to connect
as 4th parameter as shown below:
export default connect(mapStateToProps, null, null, { pure: false })(NavItems);