繁体   English   中英

使用 useState Hook 时,如何使用之前的 state 重构 if else if?

[英]How to refactor an if else if with previous state when using useState Hook?

我有 2 个details标签,每个标签都有一个控件来打开/关闭它。 代码片段在这里 单击控件 A 应打开/关闭页面 A,单击控件 B 应打开/关闭页面 B。

我是用一个if else if plus 2 useState的,当有多个details时这是不可行的。 我如何重构代码,以便可以避免if else if并以更聪明的方式检测我单击的控件?

页面.js

const Page = ({ name, isOpen, setIsOpen }) => {
  return (
    <>
      <details
        open={isOpen}
        onToggle={(e) => {
          setIsOpen(e.target.open);
        }}
      >
        <summary>Page {name} title</summary>
        <div>Page {name} contents</div>
      </details>
    </>
  );
};

export default Page;

控件.js

const Control = ({ toggle }) => {
  return (
    <>
      <a onClick={() => toggle("A")} href="#/">
        Control A
      </a>
      <br />
      <a onClick={() => toggle("B")} href="#/">
        Control B
      </a>
    </>
  );
};

应用程序.js

export default function App() {
  const [isOpenA, setIsOpenA] = useState(false);
  const [isOpenB, setIsOpenB] = useState(false);

  const toggle = (name) => {
    if (name === "A") {
      setIsOpenA((prevState) => !prevState);
    } else if (name === "B") {
      setIsOpenB((prevState) => !prevState);
    }
  };

  return (
    <div className="App">
      <Control toggle={toggle} />
      <Page name={"A"} isOpen={isOpenA} setIsOpen={setIsOpenA} />
      <Page name={"B"} isOpen={isOpenB} setIsOpen={setIsOpenB} />
    </div>
  );
}

您可以使用数组来表示开放的

const [openPages, setOpenPages] = useState([])

并切换过滤数组

const toggle = (name) => {
    if(openPages.includes(name)){
        setOpenPages(openPages.filter(o=>o!=name))
    }else{
         setOpenPages(pages=>{ return [...pages,name]}
    }
}

我个人会使用 object 作为 map 作为你的切换,就像这样:

const [isOpen, _setIsOpen] = useState({});

const setIsOpen = (pageName,value) => _setIsOpen({
 ...isOpen,
 [pageName]: value
});

const toggle = (name) => setIsOpen(name, !isOpen[name]);

然后在模板部分:

<Page name={"A"} isOpen={isOpen["A"]} setIsOpen={toggle("A")} />

通过这种方式,您可以拥有任意数量的切换开关并以任何您想要的方式使用它们

我认为这会更清晰,您还应该将各种页面名称放在一个数组中并像在

const pageNames = ["A","B"];

{
 pageNames.map( name => 
             <Page name={name} isOpen={isOpen[name]} setIsOpen={toggle(name)} />)
}

至少我是这样想的 go

Adithya 的回答对我有用。

为了将来参考,我把完整的工作代码放在这里。 不需要Page.js中的onToggle属性。 所需要的只是将正确true/false传递给Page.js中的open={isOpen}

应用程序.js:

export default function App() {
  const [openPages, setOpenPages] = useState([]);

  const toggle = (name) => {
    if (openPages.includes(name)) {
      setOpenPages(openPages.filter((o) => o !== name));
    } else {
      setOpenPages((pages) => {
        return [...pages, name];
      });
    }
  };

  return (
    <div className="App">
      <Control toggle={toggle} />
      <Page name={"A"} isOpen={openPages.includes("A")} />
      <Page name={"B"} isOpen={openPages.includes("B")} />
      <Page name={"C"} isOpen={openPages.includes("C")} />
    </div>
  );
}

页面.js

const Page = ({ name, isOpen }) => {
  return (
    <>
      <details open={isOpen}>
        <summary>Page {name} title</summary>
        <div>Page {name} contents</div>
      </details>
    </>
  );
};

Control.js 保持不变。

暂无
暂无

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

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