React.js implement menu [highlight active link]

34,522

Solution 1

maybe slightly less verbose... in Pseudocode

const menuItems = [
   'projects',
   'about',
];

class MenuExample extends React.Component {

  _handleClick(menuItem) { 
    this.setState({ active: menuItem });
  }

  render () { 
    const activeStyle = { color: '#ff3333' };

    return (
       <div className='menu'>  
         {menuItems.map(menuItem => 
            <Link 
             style={this.state.active === menuItem ? activeStyle : {}} 
             onClick={this._handleClick.bind(this, menuItem)}
            > 
              {menuItem}
            </Link>
         )}
       </div>
    );    
  }
}

Solution 2

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/subpath' activeClassName="active">about</NavLink>

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

Share:
34,522
B. Kwok
Author by

B. Kwok

Updated on July 16, 2022

Comments

  • B. Kwok
    B. Kwok almost 2 years

    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>
            )
        }
    }