首页 > 解决方案 > 反应:当另一个子菜单打开时关闭其他子菜单

问题描述

当用户打开子菜单时,我想关闭所有其他打开的子菜单。

谁能帮我找到解决方案?

我的代码:

菜单.tsx ->

const Menu: React.FC = ({ data }) => {
    return (
        <nav className={styles.headerMenu}>
            {
                data.map((item, index) => <MenuItem key={index} item={item} /> )
            }
        </nav>
    )
}

MenuItem.tsx ->

const MenuItem: React.FC = ({ item }) => {

   let [subMenuOpened, setSubMenuOpened] = useState<boolean>(false);

   const switchMenu = (condition) => setSubMenuOpened(condition !== null ? condition : !subMenuOpened)

   const SubMenu: React.FC = () => { /* Code to render submenu */ }

   return (
       <section  onMouseEnter={()=> item.subMenu && switchMenu(true)} onMouseLeave={() => item.subMenu && switchMenu(false)}>
           <a href={item.href}>{item.title}</a>
           //Render SubMenu if item has submenu and it is open
           { (item.subMenu && subMenuOpened) && <SubMenu  /> }
       </section>
   )
}

我的意思的一个例子

标签: javascriptreactjs

解决方案


@Nikki9696在评论中回答了您的问题:

通常,如果兄弟姐妹需要了解其他兄弟状态,则将状态向上移动到父级。因此,您将跟踪在 Menu 组件中打开了哪个子菜单,而不是在 MenuItem 中,然后关闭除选定的子菜单之外的所有子菜单。

因此,我将向您展示它们的含义的示例:

const Menu: React.FC = ({ data }) => {
    const keys = data.map(function(item,key) { return { key:key, close: null, item: item}});
    onOpen=(key)=>{
    // this will close all menus except the current one
    keys.forEach(x=>{
      if (x.key !== key && x.close !== null)
          x.close(); // Close should be set by child eg MenuItem.
     }) 
    }
    return (
        <nav className={styles.headerMenu}>
            {
                keys.map((item, index) => <MenuItem onOpen={onOpen} key={index} item={item} /> )
            }
        </nav>
    )
}

const MenuItem: React.FC = ({ item, onOpen }:{item: any, onOpen:Function}) => {

   let [subMenuOpened, setSubMenuOpened] = useState<boolean>(false);
    item.close = ()=> { setSubMenuOpened(false); } /// this is so the parent will trigger close
   const switchMenu = (condition) => setSubMenuOpened(condition !== null ? condition : !subMenuOpened)
   useEffect(() =>{
    if (subMenuOpened)
          onOpen(item.key); // trigger parent
   
   }, [subMenuOpened]);
   const SubMenu: React.FC = () => { /* Code to render submenu */ }

   return (
       <section  onMouseEnter={()=> item.item.subMenu && switchMenu(true)} onMouseLeave={() => item.subMenu && switchMenu(false)}>
           <a href={item.item.href}>{item.item.title}</a>
           //Render SubMenu if item has submenu and it is open
           { (item.item.subMenu && subMenuOpened) && <SubMenu  /> }
       </section>
   )
}

推荐阅读