React.js implement menu [highlight active link]

B. Kwok picture B. Kwok · Feb 17, 2017 · Viewed 21.4k times · Source

The following React.js code renders a navbar with two links named 'about' and 'project'. On page load the 'about' link is active and colored red. When the other link is clicked the state of the navbar is set to 'project', 'about' link style is set back, and 'project' is colored red.

I achieve this by attaching a click handler to both link tags, and set the state of active to the name of the event.target.innerHTML.

I'm new to react, and I feel this is a really verbose way of going about this. I am aware that there is an activeClassName prop you can pass to a react-router link, but I want a way that does not use it.

import React, { Component } from 'react'
import { Link, Route } from 'react-router'

export default class Navbar extends Component {
    constructor() {
        super();
        this.state = {
            active: 'about'
        }
        this._handleClick = this._handleClick.bind(this);
    }

    _handleClick(e) {
         this.setState({
            active: e.target.innerHTML
         });
    }

    render() {
        let aboutStyle;
        let projectStyle;

        if (this.state.active === 'about') {
            aboutStyle = { color: '#ff3333' };
            projectStyle = {};
        } else {
            aboutStyle = {};
            projectStyle = { color: '#ff3333' };
        }

        return (
        <div className='navbar'> 
            <Link to='/'><h2>BK &#47;&#47;</h2></Link>
            <div className='menu'>
                <Link style={aboutStyle} onClick={this._handleClick} to='about'>about</Link>
                <Link style={projectStyle} onClick={this._handleClick} to='projects'>projects</Link>
            </div>
        </div>
        )
    }
}

Answer

Yury Shapkarin picture Yury Shapkarin · Jan 17, 2019

At this day you can use NavLink from react-router-dom. This object supports attributes as activeClassName, activeStyle, or isActive (for functions).

import { NavLink } from 'react-router-dom';

<NavLink to='about' activeClassName="active">about</NavLink>

// Or specifing active style
<NavLink to='about' activeStyle={{color: "red"}}>about</NavLink>

// If you use deep routes and you need an exact match
<NavLink exact to='about' activeClassName="active">about</NavLink>

For more options read documentation: https://reacttraining.com/react-router/web/api/NavLink