React state打开所有子菜单,而不是只点击一个,想对我的所有菜单项只使用一个状态



我有一个react应用程序,我在组件中呈现这些信息:

const navigation = [
{
name: "Services",
description: "Our services",
href: "#",
subMenu: [
{ name: "Management" },
{ name: "Development" },
{ name: "Specialists" },
],
},
{
name: "Experts",
description: "our experts",
href: "#",
subMenu: [
{ name: "Engineers" },
{ name: "Project managers" },
{ name: "Developers" },
{ name: "Cloud solutions" },
],
}, 

所以"描述";是";标题";对于每个子菜单;name";是子菜单中的每个项目。

我正在设置以下状态:

const [ShowSubMenu, setShowSubMenu] = useState(false);

这就是我在组件中渲染子菜单的地方:

{navigation.map((item) => (
<>
<div
onClick={() => setShowSubMenu(!ShowSubMenu)}
className=" border-b-2 justify-between pb-4 pl-2 font-bold flex "
>
<h3 className=" text-roboto">{item.description}</h3>
<div className="border-solid border-b-2"></div>
<ChevronDownIcon
className={ShowSubMenu ? "rotate-90 h-5 w-5" : "h-5 w-5 "}
/>
</div>
<div className=" flex flex-col">
{item.subMenu.map((sm) => (
<div
key={sm.name}
className={!ShowSubMenu ? "hidden" : " pl-2 pt-2"}
>
{sm.name}
</div>
))}
</div>
</>
))}

我知道,由于我的子菜单根据状态打开,它将打开所有子菜单。我该如何修复,以便它知道单击了哪个项目,并且仅打开该项目的子项?我认为;键";道具会让它明白这一点。除非必要,否则我不希望每个项目都有一个单独的useState。谢谢你的帮助!

TLDR:点击更改状态,打开所有子菜单。只想在使用一个useState语句时只打开所单击项目的子菜单。

以更好地使用"useState";您可以存储应该打开的项的名称,并使用一个函数处理显示,该函数获取项的名称并在其名称与函数内的if条件匹配时展开它。例如,在这里你可以使用这个:

const [expandedSubMenu, setExpandedSubMenu] = useState();

{navigation.map((item) => (
<>
<div
onClick={() => setExpandedSubMenu(item.description)}
className=" border-b-2 justify-between pb-4 pl-2 font-bold flex "
>
<h3 className=" text-roboto">{item.description}</h3>
<div className="border-solid border-b-2"></div>
<ChevronDownIcon
className={expandedSubMenu === item.description ? "rotate-90 h-5 w-5" : "h-5 w-5 "}
/>
</div>
<div display={expandedSubMenu === item.description ? "flex" : "none"} className=" flex flex-col">
{item.subMenu.map((sm) => (
<div
key={sm.name}
className={expandedSubMenu === item.description ? "hidden" : " pl-2 pt-2"}
>
{sm.name}
</div>
))}
</div>
</>
))}

只想对我的所有菜单项使用一种状态

该状态仍然需要以某种方式能够指示哪个元素是";打开";。单个布尔值不会存储此信息。

相反,您可以跟踪状态中记录的标识符。您的记录是如何唯一标识的?name值?如果是,请将其用作状态值。类似这样的东西:

const [ShowSubMenu, setShowSubMenu] = useState();

其默认为undefined,这意味着当前没有元素是"0";打开";。然后将一设置为"1";打开":

setShowSubMenu(item.name)

隐藏它:

setShowSubMenu(undefined)

或者切换到一行,也许类似于:

setShowSubMenu(ShowSubMenu ? undefined : item.name)

或者,当点击另一个菜单并想要关闭当前打开的菜单时,可能看起来更像这样:

setShowSubMenu(ShowSubMenu === item.name ? undefined : item.name)

您可以对正在创建的单个单击处理程序进行各种调整。

然后在显示元素时,检查ShowSubMenu是否与元素匹配:

className={ShowSubMenu === item.name ? "rotate-90 h-5 w-5" : "h-5 w-5 "}

一种可能的方法是创建多个状态,每个下拉列表一个,

const [showServices, setShowService] = useState(false);
const [showExperts, setShowExperts] = useState(false);

然而,随着项目规模的扩大,这可能会变得乏味。或者,您可以将它们组合起来创建一个可以处理添加的任何布尔值的值。

const [bool, setBool] = useState({});
setBool({ ...bool, ['services']: true });
setBool({ ...bool, ['experts']: true });
console.log(bool['services'])

此方法创建一个新的键值对,而不改变对象的原始状态。然后可以使用相同的语法来更新以在真或假之间切换。并且每个布尔值可以被访问以分别处理不同的组件。

我认为值得一提的是,状态可以存储为对象,也可以存储为数组,这些数组或对象可以使用rest运算符以多种不同的方式更新

相关内容

最新更新