Skip to content

css different style to specific div created by map

I am creating a list of divs, which was created with map.

function renderButtons(){
  const options = [...Array(10).keys()] // returns [0,1,2...9]
  return _.map(options, (option)=> renderOption(option))
}

function renderOption(option:number){
  return (
    <div className="option-container" onClick={() => setLowerContainerVisible(true)}>
      <img alt="" src={"./images/feedback-icons/icon-"+option.toString()+".svg"}/>
      {option+1}
    </div>
  )
}

this renders a list of divs, and I was able to change each div background, when hover, like this:

.option-container{
  width: 76px;
  height: 100px;
  background-color: #7777ff;
  display: flex;
}

.option-container:hover{
  background-color: #adadf3;
}

I wish to be able to click on a div, and change its background color to white. everything I try will change the background of all the 10 divs to white. How can I make it so only the clicked one is changed?

Answer

I suggest that you use renderOption and renderButtons as two components rather than plain functions. In the RenderButtons component, you can use some state to maintain which item is clicked, and within RenderOption you can control whether the background color is white or not based on wehther or not the current rendered button is the clicked option. In your .map() method, you can use component rather than a function call <RenderOption option={option} ... />.

See example below:

const {useState} = React;

function RenderButtons() {
  const [clickedItem, setClickedItem] = useState(-1);
  return Array.from(
    Array(10).keys(), 
    option => <RenderOption isClicked={clickedItem === option} option={option} setClicked={setClickedItem}/>
  );
}

function RenderOption({isClicked, option, setClicked}) {
  
  const handleClick = () => {
    // setLowerContainerVisible(true) / other code to run when you click
    setClicked(option); // set to current option 
  }
  
  return (
    <div className={"option-container " + (isClicked ? "clicked" : "")} onClick={handleClick}>
      {option+1}
    </div>
  )
}

ReactDOM.render(<RenderButtons />, document.body);
.option-container {
  width: 76px;
  height: 100px;
  background-color: #7777ff;
  display: flex;
}

.option-container.clicked, .option-container:hover {
  background-color: #adadf3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

The className is a little messy as it involves a ternary, to clean this up it might be worth looking into using a node package such as classnames which allows you to easily build a list of classes based on conditions.