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



我试图在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 中复制的问题

问题

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));
};

我假设,一旦你让这个函数按预期工作,你就会实际上开始呈现你提到的下拉列表,并将实际索引传递给你的toggleDropdown函数,这样你就不会总是切换第一个索引。

最新更新