为什么 useState() 不允许连接布尔值?

Why doesn't useState() allow for concatenation of Boolean values?

我正在尝试在 React 中动态生成一些下拉菜单,每个新的下拉菜单都将引用我状态下保存的数组中的索引,但由于某些原因 setState() 布尔值不会允许串联。

import React, { useState } from "react";

function App() {
  const [dropdownName, setDropdownName] = useState(["All"]);
  const [dropdownOpen, setDropdownOpen] = useState([false]);

  const addNewDropDown = () => {
    setDropdownOpen((prev) => [...prev, false]);
    setDropdownName((prev) => [...prev, "All"]);

    console.log(dropdownName);
    console.log(dropdownOpen);
  };

  const toggleDropdown = (index) => {
    var newMap = dropdownOpen.map((e, i) => {
      if (i === index) return !dropdownOpen[i];
      else return dropdownOpen[i];
    });
    setDropdownOpen(newMap);
  };
  return (
    <div>
      <div
        style={{ backgroundColor: "red" }}
        onClick={() => {
          addNewDropDown();
          toggleDropdown(0);
        }}
      >
        Click Me
      </div>
    </div>
  );
}

/* How it looks in my acutal code for refenrece.

<Dropdown isOpen={dropdownOpen[index]} toggle={() => { toggleDropdown(index) }}>
  <DropdownToggle caret>{dropdownName[index]}</DropdownToggle>
    <DropdownMenu>
      <DropdownItem>All</DropdownItem>
      <DropdownItem divider />
      {
        dropdownFilters[index].map(item => {
          return (
            <DropdownItem>
             <div onClick={() => {
              setDropdownName(item.Name);
              getProductTypeFilters(item._id);
              addNewDropDown()
              }}>{item.Name}</div>
              </DropdownItem>)
           })
      }
  </DropdownMenu>
</Dropdown>)

*/

export default App;

旧州

["All"]
[false]

新州

["All", "All"]
[false]

期望状态

["All", "All"]
[false, false]

我试过创建一个新变量,它是旧数组并将它与新值连接起来,我试过用 prev => [...prev, false] 替换 prev => [prev, false],我什至试过做 `setDropdownOpen ([false, false]),但出于某种原因,状态似乎是不可变的。不能使用 useState() 附加布尔值吗?

这是在 coderpadCode

中复制的问题的 link

问题

onClick 处理程序最终将多个状态更新加入队列。

onClick={() => {
  addNewDropDown();
  toggleDropdown(0);
}}

来自 addNewDropDown 的更新 dropdownOpen 的状态更新被来自 toggleDropdown 的状态更新覆盖。 toggleDropdown 中的 setDropdownOpen(newMap); 未使用功能状态更新,因此它错误地从上次渲染周期的状态更新而不是从上次状态更新更新。

const toggleDropdown = (index) => {
  var newMap = dropdownOpen.map((e, i) => { // <-- dropdownOpen is unupdated state, i.e. [false]
    if (i === index) return !dropdownOpen[i];
    else return dropdownOpen[i];
  });
  setDropdownOpen(newMap); // <-- non-functional state update
};

解决方案

toggleDropdown 中使用功能状态更新。将以前的状态映射到新状态并切换与索引匹配的值。

const toggleDropdown = (index) => {
  setDropdownOpen(prev => prev.map((el, i) => i === index ? !el : el));
};

我假设一旦你让这个功能按照你的预期工作,你将实际上开始渲染你提到的下拉菜单并传递一个real 索引到您的 toggleDropdown 函数,因此您不必总是切换第一个索引。