簡體   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