简体   繁体   English

带有 React Hooks 的动态状态

[英]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.我正在尝试使用map() function 呈现一个数组,同时使用一些已建立的状态为每个元素提供其自己唯一的类名(基于索引值)。 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.我遇到了一个问题,其中className = {"header" + {index}.index}给出了正确的 state 名称(header0、header1 等),但对应于字符串而不是使用相同名称建立的 class 名称。

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 https://codesandbox.io/s/wispy-star-38qvw?fontsize=14&hidenavigation=1&theme=dark

编辑 wispy-star-38qvw

Any help is greatly appreciated!任何帮助是极大的赞赏!

You could use a single state array for visibilities.您可以使用单个 state 阵列来获得可见性。

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.此外,如果您将索引存储在单击元素的 HTML 数据集 ( data-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.您在单击的 function 中声明 2 arguments ,因此e是实际索引。

Shoud be应该是

const clicked = (index) => {

I'm afraid that is not a nice approach, but you can try this:恐怕这不是一个好方法,但你可以试试这个:

import React, { useState, useEffect } from "react";
import "./styles.css";

const data = ["James", "John", "Jessica", "Jamie"];

export default function App() {
  const headers = [];

  [headers[0], headers[1], headers[2], headers[3]] = [
    useState("visable"),
    useState("visable"),
    useState("visable"),
    useState("visable")
  ]; // each headers[index] is an array with [state, setState function]

  const clicked = (index) => {
    alert("clicked " + index);
    headers[index][1]("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={headers[index][0]}
          onClick={() => {
            clicked(index);
          }}
        >
          {/* classname should be the state "header0" but right now its just a string */}
          Hello {value}!
        </h1>
      ))}
    </div>
  );
}

the code pen: https://codesandbox.io/s/agitated-rain-o31ms代码笔: https://codesandbox.io/s/agitated-rain-o31ms

You can change the way you are structing the state to an array, then the click function will turn it invisible by index您可以更改将 state 构造为数组的方式,然后单击 function 将通过索引使其不可见

const data = ["James", "John", "Jessica", "Jamie"];

export default function App() {
    const [headersVisible, setHeaderVisible] = useState(
        data.map(() => "visible")
    );

    const clicked = (index) => {
        setHeaderVisible(
            headersVisible.map((val, ix) => (index === ix ? "invisible" : val))
        );
    };

    return (
        <div className="App">
            <h1>Sample Project</h1>
            {data.map((value, index) => (
                <h1
                    key={index}
                    className={headersVisible[index]}
                    onClick={()=>clicked(index)}
                >
                    {/* classname should be the state "header0" but right now its just a string */}
                    Hello {value}!
                </h1>
            ))}
        </div>
    );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM