Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic States with React Hooks

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

Edit wispy-star-38qvw

Any help is greatly appreciated!

like image 433
Jschriemer Avatar asked Mar 18 '26 11:03

Jschriemer


2 Answers

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>
like image 197
AKX Avatar answered Mar 21 '26 00:03

AKX


You are declaring 2 arguments in clicked function so e is the actual index.

Shoud be

const clicked = (index) => {
like image 25
uke Avatar answered Mar 20 '26 23:03

uke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!