You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于HeadlessUI与React的移动端嵌套抽屉导航问题排查

移动端嵌套抽屉导航问题:点击分类始终显示最后一个分类内容

我正在复刻移动端嵌套抽屉导航,抽屉能正常打开,但点击任意分类时,始终只显示最后一个分类(比如Events、Retailers)的内容,而非选中的分类。

菜单JSON

{"items": [{"title": "Vaporizers","url": "","items": [{"title": "FOR FLOWER & CONCENTRATES","items": [{"title": "COMPANY PLUS","url": "/products/COMPANY-plus"},{"title": "COMPANY MINI","url": "/products/COMPANY-mini"}],"url": "/collections/dry-herb-and-concentrate-vaporizers"},{"title": "FOR OIL EXTRACT PODS","items": [{"title": "COMPANY ERA","url": "/products/COMPANY-era"},{"title": "ERA PRO","url": "/products/era-pro"}],"url": "/collections/oil-extract-vape-pens"},{"title": "ON SALE","items": [],"url": "/collections/sale"}],"useShowcaseComponent": true},{"title": "Cannabis","url": "","items": [{"title": "COMPANY Infused","url": "/products/cannabis/COMPANY-infused"},{"title": "COMPANY Live Rosin","url": "/products/cannabis/COMPANY-live"},{"title": "COMPANY Diamonds","url": "/products/cannabis/COMPANY-diamonds"}]},{"title": "Find","url": "","items": [{"title": "Events","url": "/pages/COMPANY-events"},{"title": "Retailers","url": "/pages/store-locator"}]}]}

Header组件代码

<MenuDrawer isOpen={isMenuOpen} onClose={closeMenu}>
  <TopLevelMenuNav
    menu={menu}
    closeMenuItem={closeMenuItem}
    openMenuItem={openMenuItem}
    isMenuItemOpen={isMenuItemOpen}
  />
</MenuDrawer>

TopLevelMenuNav组件代码

{(menu?.items || []).map((category) => (
  <div key={category.title}>
    <button
      onClick={openMenuItem}
      className="flex flex-row justify-between p-4 align-middle text-2xl"
    >
      {category.title}
      <ChevronRightIcon className="ml-1 h-4 w-4 self-center" />
    </button>
    <MenuDrawer isOpen={isMenuItemOpen} onClose={closeMenuItem}>
      <MenuItemNav category={category} />
    </MenuDrawer>
  </div>
))}
<div className="flex flex-col">
  {category.items.map((section) => (
    <div key={section.title} className="flex flex-col hover:bg-gray-50">
      <a href={section.url} className="py-4 px-6 font-normal text-gray-500">
        {section.title}
      </a>
      {section?.items && (
        <div className="flex flex-col pl-8">
          {section.items.map((item) => (
            <div key={item.title} className="flex hover:bg-gray-50">
              <a
                href={item.url}
                className="py-2 font-semibold text-gray-900"
              >
                {item.title}
              </a>
            </div>
          ))}
        </div>
      )}
    </div>
  ))}
</div>

我曾尝试使用useState来设置MenuItemNav组件中显示的内容,但问题依旧,仍只显示最后一个分类的内容。


问题原因及解决方案

问题核心

所有分类共用同一个布尔型isMenuItemOpen状态,且每个分类都渲染了独立的MenuDrawer。点击任意分类触发openMenuItem时,所有抽屉的isOpen都会变为true,但DOM渲染顺序中最后一个抽屉会覆盖前面的,导致看起来只显示最后一个分类的内容。

修改步骤

  1. 调整状态类型:将单个布尔值isMenuItemOpen改为记录当前打开分类的标识(比如分类标题),用于精准控制对应抽屉的显示。
  2. 更新点击事件:点击分类按钮时,把当前分类的标识存入状态;关闭抽屉时清空状态。
  3. 匹配抽屉显示条件:每个抽屉只在当前分类标识与状态匹配时才打开。

修改后的代码示例

Header组件(状态调整)
// 替换原有的isMenuItemOpen状态
const [openCategory, setOpenCategory] = useState(null);

// 更新打开/关闭函数
const openMenuItem = (categoryTitle) => {
  setOpenCategory(categoryTitle);
};

const closeMenuItem = () => {
  setOpenCategory(null);
};

// 传递更新后的props给TopLevelMenuNav
<MenuDrawer isOpen={isMenuOpen} onClose={closeMenu}>
  <TopLevelMenuNav
    menu={menu}
    closeMenuItem={closeMenuItem}
    openMenuItem={openMenuItem}
    openCategory={openCategory}
  />
</MenuDrawer>
TopLevelMenuNav组件(匹配显示条件)
{(menu?.items || []).map((category) => (
  <div key={category.title}>
    <button
      onClick={() => openMenuItem(category.title)}
      className="flex flex-row justify-between p-4 align-middle text-2xl"
    >
      {category.title}
      <ChevronRightIcon className="ml-1 h-4 w-4 self-center" />
    </button>
    <MenuDrawer 
      isOpen={openCategory === category.title} 
      onClose={closeMenuItem}
    >
      <MenuItemNav category={category} />
    </MenuDrawer>
  </div>
))}

这样修改后,每个分类的抽屉只有在当前选中的分类标识与状态匹配时才会打开,不会再出现多个抽屉同时显示、最后一个覆盖的问题。


内容的提问来源于stack exchange,提问作者G.Rose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:47:01