7

I have a list of links.

I'm adding a class on click, called "is-active". At the same time, I would like to remove all the existing "is-active"s except for on the link I clicked on. There may only be one element with the class "is-active" as that will 'live' page. (Using bulma css)

Here's the code I've tried so far. It's adding classes but not removing them.

class Menu extends Component {

    constructor(props) {
        super(props);
        this.state = {addClass: false}
    };

    handleClick(e) {
        if(e.target.class === 'is-active'){
            e.target.className = '';
            console.log('remove')
        }else{
            e.target.className = 'is-active';
            console.log('add class')
        }
    }  

    render() {
        <ul className="menu-list">
            { this.props.getList.map(list =>
                <Link onClick={this.handleClick.bind(this)} key={list.id} to="">{list.title}</Link>                    
            )}
        </ul>
    }

}

export default SideMenu;

Advice would be sooo much appreciated.

3 Answers 3

20

You must avoid touching the DOM by yourself, let's React do it for you.

You want to keep a signal in the state that tell's you whether an element in the list is active or not, and use that signal to set a class or not in your rendering phase:

state = {
  activeId: null  // nothing selected by default, but this is up to you...
}

handleClick(event, id) {
  this.setState({ activeId: id })
}

render() {
  <ul className="menu-list">
  {
    this.props.getList.map(list =>
      <Link key={ list.id }
            className={ this.state.activeId === list.id && 'is-active' }
            onClick={ this.handleClick.bind(this, list.id) } 
            to="">
        { list.title }
      </Link>                    
    )
  }
  </ul>
}

This way, at each render, the id of each item in your getList prop is compared to the one you keep in your state, then:

  1. if it's the active id, it assign the 'is-active' class;
  2. if it's not the active one, it clears the previous className (in case it was 'is-active';

Hope it helps :)

Sign up to request clarification or add additional context in comments.

Comments

7

If you are using React avoid DOM manipulation directly. The only thing you are changing should be state, let React deal with DOM.

For changing class names I would recommend library called classnames (https://github.com/JedWatson/classnames). It will only occupy 588 bytes in your bundle size.

If you don't want to use third party library then use JavaScript's template literals to do this.

Example:

<div className={ `list-item ${this.state.active ? "active" : ""}` }>...</div>

Comments

2

If your are using react-router for handling navigation in your app you can use the <NavLink> component that accepts a prop for adding a class when the url matches.

<NavLink to="/yourPath" activeClassName="is-active">Home<NavLink>

To use NavLink in your project, you must import it

import { NavLink, Route } from 'react-router-dom'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.