React Js/Menu,菜单项下拉,菜单项处于活动状态



hi我有一个带有标记结构的菜单<li><a> 其中一些菜单项将是下拉

然后我创建了一个状态数组来存储我的所有菜单项,当一个菜单项被点击时,它需要为true,而其他所有菜单项都为false,也就是说,在这个数组中,只有一个项目可以为true,这样我就可以显示我的下拉项,甚至可以对我的活动项应用css效果,但由于某种原因,当点击时,我的状态永远不会变为true:

代码:

const MenuItem = ({ tag, visibleMenu }) => {
const { name, link, dropdownItems } = tag;
return (
<NavLi>
<a>{name}</a>
{visibleMenu[name] && dropdownItems ? (
<DropDown>
{dropdownItems.map(item => (
<li>
<a href={item.link}>{item.name}</a>
</li>
))}
</DropDown>
) : (
""
)}
</NavLi>
);
};
const MenuBar = props => {
const MenuTags = [
{
name: "home",
link: "/",
dropdownItems: [
{ name: "one", link: "/aa" },
{ name: "two", link: "/b/" }
]
},
{
name: "about",
link: "../abovisibleMenuut",
dropdownItems: [
{ name: "one", link: "/aa" },
{ name: "two", link: "/b/" }
]
},
{ name: "not dropdown", link: "../dashboard" },
{ name: "not dropdown", link: "../dashboard/about" }
];
const [visibleMenu, setVisibleMenu] = useState(
MenuTags.reduce((r, e) => ((r[e.name] = false), r), {})
),
onUpdateVisibility = item => {
const visibleMenuCopy = { ...visibleMenu };
Object.keys(visibleMenuCopy).forEach(
key => (visibleMenuCopy[key] = key === item)
);
setVisibleMenu(visibleMenuCopy);
};
console.log(visibleMenu);
return (
<NavUl isOpen={props.isOpen}>
{MenuTags.map(item => (
<MenuItem
tag={item}
visibleMenu={visibleMenu}
onClick={() => onUpdateVisibility(item)}
/>
))}
<li>
<FontAwesomeIcon
onClick={() => props.setOpenBox(!props.isOpen)}
className="searchIcon"
rotation={90}
icon={faSearch}
size="1x"
fixedWidth
color="rgba(0, 0, 0, 0.08);"
/>
</li>
</NavUl>
);
};

示例:

https://codesandbox.io/s/lucid-sammet-9qim9

我相信我的问题出在我的状态:

const [visibleMenu, setVisibleMenu] = useState(
MenuTags.reduce((r, e) => ((r[e.name] = false), r), {}),
),
onUpdateVisibility = item => {
const visibleMenuCopy = { ...visibleMenu };
Object.keys(visibleMenuCopy).forEach(
key => (visibleMenuCopy[key] = key === item),
);
setVisibleMenu(visibleMenuCopy);
};
{MenuTags.map(item => (
<MenuItem
tag={item}
visibleMenu={visibleMenu}
onClick={() => onUpdateVisibility(item)}
/>
))}

但这是我发现的唯一一种方法,当点击时,一次只能使一个状态为真

问题是事件处理程序所在的组件没有返回任何具体的HTML元素。MenuTag返回NavLI,这是一个样式组件,它返回一个li。我不是样式组件的大师,但我认为通常情况下,事件处理程序需要附加到DOM元素,而不是抽象的React组件。

此外,我认为你可以极大地简化这一点。这个怎么样:

const [visible, setVisible] = useState('none'),
{MenuTags.map( (item, index) => (
<MenuItem
key={index}
tag={item}
visibleMenu={visible === index ? true : false}
onClick={() => setVisible(index)}
/>
))}

因此,这意味着在这个组件中,我们用visible状态变量跟踪哪个项目是可见的,它将是可见项目的索引。onClick处理程序将此值更改为所单击项目的索引。然后,道具visibleMenu将检查此条件,确保该MenuTag的索引与状态中的索引相同。

编辑

我改变了一些事情。我们没有从MenuItem中控制状态,而是将一些道具传递给MenuItem,并在MenuItem的子组件NavLI中控制它们,NavLI接受事件处理程序


const MenuBar = props => {
const [visible, setVisible] = useState('none')
console.log(visible);
return (
<NavUl isOpen={props.isOpen}>
{MenuTags.map( (item, index) => (
<MenuItem
key={index}
index={index}
tag={item}
setVisible={setVisible}
visibleMenu={visible === index ? true : false}
/>
))}
// Inside NavLI
const MenuItem = ({ tag, visibleMenu, setVisible, index }) => {
...
return (
<NavLi onMouseEnter={ () => { console.log(index); setVisible(index) }} 
onMouseLeave={() => { setVisible('none')}} >
...

我将处理程序更改为onMouseEnteronMouseLeaveonClick会起作用,但您需要一个全局事件处理程序来将页面setVisible恢复为"none",这样当您单击页面上的其他任何位置时,选项卡都会关闭。这里有更多的细微差别,但我的例子应该有效。

工作代码沙盒

最新更新