0

I'm fairly new to React and struggle to find a suitable answer to my question. I've got a list with multiple buttons (23) and want to add an .active class to every individual button that has been clicked. I am saving the buttons "value" in a a state array for later usage. Ergo, there can be multiple buttons with an active class and no buttons with the respective class.

class DistrictModal extends React.Component {

constructor(props) {
    super(props);

    this.state = {
        selectedDistricts: []
    }
}

addDistrictToList = (e) => {
    this.setState(prevState => ({
        selectedDistricts: [...prevState.selectedDistricts, e]
    }));

}

render() {

<div className="list-group">
  <button type="button" onClick={() => this.addDistrictToList("1")} > 1. bezirk </button>
  <button type="button" onClick={() => this.addDistrictToList("2")} > 2. bezirk </button>
  <button type="button" onClick={() => this.addDistrictToList("3")} > 3. bezirk </button>
</div>

}}
user3174027
  • 47
  • 2
  • 8

3 Answers3

2

Try this:

<button type="button" onClick={() => this.addDistrictToList("1")}
className={this.state.selectedDistricts.includes(1) ? 'active' : ''}> 1. bezirk </button>

This adds the class active, if the list contains the value "1"

Source: StackOverflow

Tobias Schäfer
  • 1,330
  • 2
  • 17
  • 35
0

Here's the cleaner code with React Hooks:

import React, { useState } from 'react'

const DistrictModal = () => {

const [selectedDistricts, setSelectedDistricts] = useState([])

const addDistrictToList = id => {
    setSelectedDistricts([
        ...selectedDistricts,
        id
    ])
}

const isDistrictSelected = id => {
    return selectedDistricts.indexOf(id) !== -1
}

return(
   <div className="list-group">
      <button type="button" className={isDistrictSelected(1) && 'active'} onClick={() => this.addDistrictToList(1)} > 1. bezirk </button>
      <button type="button" className={isDistrictSelected(2) && 'active'} onClick={() => this.addDistrictToList(2)} > 2. bezirk </button>
      <button type="button" className={isDistrictSelected(3) && 'active'} onClick={() => this.addDistrictToList(3)} > 3. bezirk </button>
    </div>
)
}
Ali Mousavi
  • 855
  • 7
  • 15
-1

What you can do is create an array of buttons to render. Then for each index you remember if it has been clicked or not. Something approximately along the following lines (untested, I hope you get the gist, else I can further elaborate):

class DistrictModal extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      selectedDistricts: [],
      buttons: [
        {title: 'bezirk'},
      ],
      clickedButtonIndices: [],
    }
  }

  addDistrictToList(i) {
    this.setState(prevState => ({
      selectedDistricts: [...prevState.selectedDistricts, i]
    }));
  }

  onButtonClick(e, i) {
    this.addDistrictToList(i);
    this.clickedButtonIndices.push(i);
  }

  render() {
    return (
      <div className="list-group">
        {
          this.buttons.map((button, i) => {
            const isActive = this.state.clickedButtonIndices.includes(i);
            return (
              <button key={i} type="button" onClick={(e) => this.onButtonClick(e, i)} className={isActive ? 'active' : ''}>{button.title}</button>
            );
          })
        }
      </div>
    );
  }
}

Maybe you'll have to do a this.forceUpdate() after the this.clickedButtonIndices.push(i);, as I don't think it will trigger a rerender.

minitauros
  • 1,920
  • 18
  • 20