Search code examples
javascriptreactjsreact-dom

React - toggle css class


i want to be able to toggle class "active" on/off on a single item of a list. Say we have a list of elements:

<ul>
  <li><a href="#" className="list-item">First</a></li>
  <li><a href="#" className="list-item">Second</a></li>
  <li><a href="#" className="list-item">Third</a></li>
</ul>

and I want to be able to add class "active" on a second element on click. I cannot use state for that, because it would change the classes of other 2 elements, if we add the condition there, right ?

So the solution could be to create a sub-component say <ListItem /> that could have its own state and own onclick method, that would change only his own class. But then, when we want to remove class "active" on other elements on click, this sub-component would have to dispatch method to a parent to remove class from other elements. It seems pretty complicated for a task of a easy kind ( you know the 10secs-in-jquery kind).

Does anyone have an easier solution for this ?

It would be very nice to not have to use another big npm module for this, document.getElementsByClassName (obviously) nor refs.


Solution

  • you can manage the selected state outside the item component and pass it as a prop.
    An event handler of onSelect / onClick can trigger and change the state.

    const data = [1,2,3,4,5];
    
    class List extends React.Component {
    	constructor(props){
    			super(props);
          
          this.state = {
          	selectedItem: 0
          };
          this.onSelect = this.onSelect.bind(this);
      }
      
      onSelect(id){
      	this.setState({
        	selectedItem: id
        });
      }
      
      render() {
      	const {selectedItem} = this.state;
      	return ( 
          <ul>
              {data.map((d, index) => {
              	return <ListItem 
                          key={index}
                          selected={index + 1  == selectedItem}
                          value={d}
                          id={d}
                          onSelect={this.onSelect}
                        />
              })}
              
          </ul>
        )
      }
    }
    
    const ListItem = (props) => {
    
      const onSelect = (e) => {
      	props.onSelect(e.target.id);
      }
      
      const className = props.selected && "selected";
      	
    	return <li className={className} id={props.id} onClick={onSelect}>{props.value}</li>
    }
    
    ReactDOM.render(<List />, document.getElementById("root"));
    ul{
      list-style: none;
    }
    
    li{
        padding: 5px;
        border: 1px solid #ccc;
        cursor: pointer;
    }
    
    li.selected{
      background-color: green;
      color: #fff;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>