Reputation: 744
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.
Upvotes: 7
Views: 33635
Reputation: 931
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'
Upvotes: 2
Reputation: 3725
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:
className
(in case it was 'is-active';Hope it helps :)
Upvotes: 20
Reputation: 1059
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>
Upvotes: 7