'Set acitve classname to multiple items in react js (map)
I need to set the active classname to multiple onclick items inside a .map
I have implemented by it only keeps track of current click active index
I need the list of active items that were clicked.
const [activeIndex, setActiveIndex] = useState(-1);
return (
<>
{data?.map((item, index) => {
return (
<Col
className={`mb-3 ${
index === activeIndex ? "selected" : "notselected"
}`}
key={item.id}
onClick={() => {
handleclick(item.id, index, item.name);
setActiveIndex(index);
}}
xs={6}
md={2}
>
<div
className={`common-cat-listener pop-cat-${item.id} all`}
>
<h4 className="cat-text py-4 px-3">{item.name}</h4>
</div>
</Col>
);
})}
</>
Solution 1:[1]
Since you need to keep track of multiple items, the state for that can't be just a single number (unless you use prime number multiplication or something similarly absurd). Use an array of booleans instead.
const [activeIndicies, setActiveIndicies] = useState(() => data.map(() => false));
return (
<>
{data?.map((item, index) => {
return (
<Col
className={`mb-3 ${
activeIndicies[index] ? "selected" : "notselected"
}`}
key={item.id}
onClick={() => {
handleclick(item.id, index, item.name);
setActiveIndicies(activeIndicies.map((bool, j) => j === index ? true : bool);
}}
...
Tiny demo:
const App = () => {
const data = [1, 2, 3];
const [activeIndicies, setActiveIndicies] = React.useState(() => data.map(() => false));
return data.map((item, index) => {
return (
<span
className={activeIndicies[index] ? "selected" : "notselected"}
onClick={() => {
setActiveIndicies(activeIndicies.map((bool, j) => j === index ? true : bool));
}}
>{item}</span>
)
})
};
ReactDOM.render(<App />, document.querySelector('.react'));
.selected {
color: yellow;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
Solution 2:[2]
You seem to have and id for your items. I would assume they are all unique. If so, you could change your state for and array instead. The on Click method would then add the items.id inside the array and instead of doing
index === activeIndex
You could do :
activeIds.includes(item.id) ? // rest of code
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | SFournier |