Reputation: 349
I wanted to add an 'active' class to a menu element, written in ReactJS. I tried doing it with the conventional JS method, but it failed. A click on any <li> tag, should result is removal of the 'active' class from all the <li>, and retain/ add it only to the one list tag in which the click was triggered.
Note: I know it may seem very naive on my part, but I'm just starting with ReactJS. Please ignore the stupidity.
import React, { Component } from 'react';
class Sidebar extends Component{
render(){
return(
<div className="sidebarContainer p-2">
<div className="mainMenu">
<ul className="levelOne pl-0">
<li className="mb-3 pl-2 menuTitle active" id="MenuTitle1">
...
</li>
<li className="mb-3 pl-2 menuTitle" id="MenuTitle2" onClick={this.clickMenu.bind(this,'MenuTitle2')}>
...
</li>
<li className="mb-3 pl-2 menuTitle" id="MenuTitle3" onClick={this.clickMenu.bind(this,'MenuTitle3')}>
...
</li>
</ul>
</div>
</div>
);
}
clickMenu(id){
// Add class 'active' on the clicked <li>, and remove from all other <li>
}
}
export default Sidebar;
I saw a similar question here, but that couldn't help me.
Upvotes: 1
Views: 6051
Reputation: 5912
Another way of just make using initialstate
and setState
.
import React, { Component } from "react";
class Sidebar extends Component {
constructor(props) {
super(props);
this.initialState = {
MenuTitle1: "active",
MenuTitle2: "",
MenuTitle3: ""
};
this.state = this.initialState;
}
render() {
return (
<div className="sidebarContainer p-2">
<div className="mainMenu">
<ul className="levelOne pl-0">
<li
className={`mb-3 pl-2 menuTitle ${this.state.MenuTitle1} `}
id="MenuTitle1"
onClick={this.clickMenu.bind(this, "MenuTitle1")}
>
one
</li>
<li
className={`mb-3 pl-2 menuTitle ${this.state.MenuTitle2}`}
id="MenuTitle2"
onClick={this.clickMenu.bind(this, "MenuTitle2")}
>
two
</li>
<li
className={`mb-3 pl-2 menuTitle ${this.state.MenuTitle3}`}
id="MenuTitle3"
onClick={this.clickMenu.bind(this, "MenuTitle3")}
>
three
</li>
</ul>
</div>
</div>
);
}
clickMenu(id) {
this.setState(this.initialState);
this.setState({
[id]: "active"
});
}
}
export default Sidebar;
Upvotes: 1
Reputation: 443
Like Bhojendra suggested store datas linked to your display inside your state then when you want to update the display of your component use the method setState, this will trigger render again (react style).
import React, { Component } from 'react';
import ReactDOM from "react-dom";
class Sidebar extends Component {
constructor() {
super();
this.state = {
activeMenuId: "MenuTitle1"
};
}
render() {
return (
<div className="sidebarContainer p-2">
<div className="mainMenu">
<ul className="levelOne pl-0">
<li className={`mb-3 pl-2 menuTitle ${this.state.activeMenuId === "MenuTitle1" ? "active" : ""}`} id="MenuTitle1" onClick={this.clickMenu.bind(this, 'MenuTitle1')}>
1
</li>
<li className={`mb-3 pl-2 menuTitle ${this.state.activeMenuId === "MenuTitle2" ? "active" : ""}`} id="MenuTitle2" onClick={this.clickMenu.bind(this, 'MenuTitle2')}>
2
</li>
<li className={`mb-3 pl-2 menuTitle ${this.state.activeMenuId === "MenuTitle3" ? "active" : ""}`} id="MenuTitle3" onClick={this.clickMenu.bind(this, 'MenuTitle3')}>
3
</li>
</ul>
</div>
</div>
);
}
clickMenu(id) {
// Add class 'active' on the clicked <li>, and remove from all other <li>
this.setState({activeMenuId: id});
}
}
export default Sidebar;
ReactDOM.render(<Sidebar />, document.body);
Upvotes: 1
Reputation: 104369
Idea is, store the id of clicked item in state
variable and put the check with className. If item's id is same as state value then only assign the className active
.
Write it like this:
class Sidebar extends Component{
constructor() {
super()
this.state = {
activeItem: 'MenuTitle1'
}
}
clickMenu(id){
// Add class 'active' on the clicked <li>, and remove from all other <li>
this.setState({
activeItem: id,
})
}
getClassName(id) {
if(id === this.state.activeItem) return 'mb-3 pl-2 menuTitle active'
return 'mb-3 pl-2 menuTitle'
}
render(){
return(
<div className="sidebarContainer p-2">
<div className="mainMenu">
<ul className="levelOne pl-0">
<li
id="MenuTitle1"
className={this.getClassName('MenuTitle1')}
onClick={this.clickMenu.bind(this,'MenuTitle1')}>
...
</li>
<li
id="MenuTitle2"
className={this.getClassName('MenuTitle2')}
onClick={this.clickMenu.bind(this,'MenuTitle2')}>
...
</li>
<li
id="MenuTitle3"
className={this.getClassName('MenuTitle3')}
onClick={this.clickMenu.bind(this,'MenuTitle3')}>
...
</li>
</ul>
</div>
</div>
);
}
}
Upvotes: 3
Reputation: 85545
You can maintain the state for clicked menu item:
clickMenu(id){
this.setState({activeMenu: id})
}
Then, define className like this:
className={
this.state.activeMenu == id {/* eg. "MenuTitle1" */}
? 'mb-3 pl-2 menuTitle active'
: 'mb-3 pl-2 menuTitle'
}
Upvotes: 1