I am trying to render an array using the map() function while giving each element its own unique className (based on the index value) using some established states. An element should change colour when clicked using hooks. I've run into a problem where className = {"header" + {index}.index} gives the correct state name (header0, header1, etc.) but corresponds to a string rather than the class names established with the same names.
const data = ["James", "John", "Jessica", "Jamie"];
export default function App() {
const [header0, setHeader0] = useState("visable");
const [header1, setHeader1] = useState("visable");
const [header2, setHeader2] = useState("visable");
const [header3, setHeader3] = useState("visable");
const clicked = (index) => {
if (index === 0) {
setHeader0("invisible");
} else if (index === 1) {
setHeader1("invisible");
}
/*Is there an alternative like {setHeader + index} instead of this loop?*/
};
return (
<div className="App">
<h1>Sample Project</h1>
{data.map((value, index) => (
<h1
className={"header" + { index }.index}
onClick={() => {
clicked(index);
}}
>
{/* classname should be the state "header0" but right now its just a string */}
Hello {value}!
</h1>
))}
</div>
);
}
Here is a code sandbox of what I am trying, with a few comments where things are going wrong. Am I going about this problem the correct way? https://codesandbox.io/s/wispy-star-38qvw?fontsize=14&hidenavigation=1&theme=dark
Any help is greatly appreciated!
You could use a single state array for visibilities.
In addition, if you stash the index in the clicked element's HTML dataset (data-index), you don't need a separate closure/function for each index.
const data = ["James", "John", "Jessica", "Jamie"];
function App() {
const [visibilities, setVisibilities] = React.useState(() => data.map((x) => true));
const handleClick = (event) => {
const index = parseInt(event.currentTarget.dataset.index, 10);
const newVisibilities = [...visibilities];
newVisibilities[index] = !newVisibilities[index];
setVisibilities(newVisibilities);
};
return (
<div className="App">
{data.map((value, index) => (
<h1 data-index={index} onClick={handleClick} className={visibilities[index] ? "selected" : undefined}>
Hello {value}, you are {visibilities[index] ? "visible" : "hidden"}!
</h1>
))}
</div>
);
}
ReactDOM.render(<App />, document.querySelector("main"));
.selected {
background: lightgreen;
}
h1 {
cursor: pointer;
user-select: none;
}
<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>
<main></main>
You are declaring 2 arguments in clicked function so e is the actual index.
Shoud be
const clicked = (index) => {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With