我有一个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运算符以多种不同的方式更新