Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Rowan Blackwood
Rowan Blackwood
5,220 Points

Adding a class on click in React

I'm having trouble adding a class to the li I have clicked in react.

// Parent component

class Search extends Component {
    constructor(props) {
      super(props)
      this.state = {
        appliedFacets: [],
        active: false,
      };
      this.handleAddFacet = this.handleAddFacet.bind(this);
    }

handleAddFacet(item, e) {
      this.setState({
        appliedFacets: [...this.state.appliedFacets, item],
        active: true
      });
    }

}

The handleAddFacet function gets passed down as props to a child component which uses a callback function to pass the item back to the 'App component' (in this case 'Search')

// Child component

{props.items.map(item => (
          <li className={props.active ? 'search-facet-filters__filter active': 'search-facet-filters__filter'} 
          key={item.id}
          onClick={(e) => props.handleAddFacet(item, e)}>
            {item.name}
          </li>
          ))}

The item gets passed back correctly, but I can't figure out how to add the active state to the li I have clicked. Currently every li gets the class of active when ANY li is clicked. I'm assuming it needs to be bound to the event or something but not to sure.

Any help would be great!

Thanks

1 Answer

Sam Gord
Sam Gord
14,084 Points

Hi, honestly , your code didn't provide enough info to debug it . or at least i felt like that. but , based on your code i made a little very simple app to show you how to change the active state for EACH object in an array that we use to render our list items. index.js -->

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

// importing components

import Parent from "./components/Parent";

function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

parent component -->

import React, { Component } from "react";

import Child from "./Child";

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      appliedFacets: [
        {
          id: 1,
          name: "ice cream",
          active: false
        },
        {
          id: 2,
          name: "pop corn",
          active: false
        },
        {
          id: 3,
          name: "chocolate",
          active: false
        }
      ]
    };
    this.handleAddFacet = this.handleAddFacet.bind(this);
  }

  handleAddFacet(index) {
    let arrCopy = [...this.state.appliedFacets];
    arrCopy[index].active = !arrCopy[index].active;
    this.setState({
      appliedFacets: arrCopy
    });
  }

  render() {
    return (
      <div>
        <p>this is the parent component</p>
        <Child clicked={this.handleAddFacet} items={this.state.appliedFacets} />
      </div>
    );
  }
}

export default Parent;

child component --->

import React from "react";

const Child = props => {
  return (
    <div>
      <p>this is the child component</p>
      {props.items.map((item, index) => (
        <li
          className={
            item.active
              ? "search-facet-filters__filter active"
              : "search-facet-filters__filter"
          }
          key={item.id}
          onClick={e => props.clicked(index, e)}
        >
          {item.name}
        </li>
      ))}
    </div>
  );
};

export default Child;

and also the styles which you can add or remove to each li item by clicking on it -->

.App {
  font-family: sans-serif;
  text-align: center;
}

.search-facet-filters__filter {
  background: white;
  cursor: pointer;
  border: 1px solid #ccc;
  font-weight: bold;
  padding: 10px;
  margin: 5px 0;
  transition: all 0.2s;
}

.search-facet-filters__filter:hover {
  box-shadow: 0 2px 4px #eee;
  letter-spacing: 2px;
}

.active {
  background: orange;
  color: white;
}

hope it helps . Happy Coding ;)