简体   繁体   English

React 可折叠菜单组件,当我单击类别标题时应该展开但不会显示子链接

[英]React collapsible menu component that should expand when I click on a category title but won't show the children links

I created a component for a collapsible navigation menu.我为可折叠导航菜单创建了一个组件。 This menu has a map of children categories and each one of these categories has a list of links.此菜单有 map 个子类别,每个类别都有一个链接列表。

This menu has a button to expand and collapse the navigation menu panel.此菜单有一个用于展开和折叠导航菜单面板的按钮。

When I click in one of the category titles the menu should expand and at the same time show the corresponding links, however with this code only expands the navigation menu panel but not show the children links.当我单击其中一个类别标题时,菜单应该展开并同时显示相应的链接,但是使用此代码仅展开导航菜单面板但不显示子链接。

The collapsed structure is something like this:倒塌的结构是这样的:

Cat A
Cat B
Cat C

The expanded structure with children links is something like this:带有子链接的扩展结构是这样的:

Category A
|
|--Link A1
|--Link A2
|--Link A3

Category B
|
|--Link B1
|--Link B2
|--Link B3

Category C
|
|--Link C1
|--Link C2
|--Link C3

This is the menu component:这是菜单组件:

import React, { useState } from "react";
import { NavItem } from "./NavItem";

export function Navigation({
  menuItems,
}) {
  const [opened, setPanelOpened] = useState(false);

  return (
    <nav className={opened ? "expanded" : "collapsed"}>
      <button
        onClick={() => {
          setPanelOpened(!opened);
        }}
      >
        Toggle Menu
      </button>

      {menuItems.map((item) => (
        <NavItem menuItem={item} setPanelOpened={setPanelOpened} panelOpened={opened} />
      ))}
    </nav>
  );
}

This is the NavItem component for categories:这是类别的 NavItem 组件:

import React, { useState } from "react";

export function NavItem({
  menuItem,
  panelOpened,
  setPanelOpened,
}) {
  const [categoryOpened, setCategoryOpened] = useState(false);

  return (
    <div
      // If category is opened, should toggle a class to show / hide the children elements
      className={categoryOpened ? "opened" : "closed"}
    >
      <h2
        onClick={() => {
          // Should display the children menu items when I click the button
          setCategoryOpened(!categoryOpened);
          if (!panelOpened) {
            setPanelOpened(true);
          }
        }}
      >
        Parent Category
      </h2>

      {menuItem.children?.map((subItem) => (
        <a href={subItem.link}>
          {subItem.label}
        </a>
      ))}
    </div>
)
}

setCategoryOpened(!categoryOpened) won't work at the same time with setPanelOpened(true) , only expands the menu and won't shows the children category items. setCategoryOpened(!categoryOpened)不会与setPanelOpened(true)同时工作,只会展开菜单,不会显示子类别项目。 How can I trigger both hooks at the same time?如何同时触发两个钩子?

When I click on a category title the menu should expand and show the corresponding children links at the same time, but only menu expansion happens, I have to click again to show the children links当我点击一个类别标题时,菜单应该展开并同时显示相应的子链接,但只有菜单展开发生,我必须再次点击才能显示子链接

You're using two clicks events, if you want you can attach an useEffect hook that depends on your parent state, and when it changes the children set the states as true and open.您正在使用两个点击事件,如果您愿意,可以附加一个依赖于您的父级 state 的 useEffect 挂钩,并且当它更改子级时,将状态设置为 true 和 open。 As I cannot run your code, it's hard to debug, but the hint is to start putting console.log() to see where's the issue.由于我无法运行您的代码,因此很难调试,但提示是开始放置console.log()以查看问题出在哪里。 Keep in mind that setState() method is asynchronous, so if you're trying to get the updated value in a sync function maybe it has the outdated value at that moment.请记住, setState()方法是异步的,因此如果您尝试在同步 function 中获取更新值,那么它可能在那一刻具有过时的值。

You can debug this as I told you with logs everywhere, to see what's happening.你可以像我告诉你的那样调试它,到处都有日志,看看发生了什么。 Hope it helps, if not please provide a code sandbox or a working snippet for us to debug properly your code.希望对您有所帮助,如果没有,请提供代码沙箱或工作片段,以便我们正确调试您的代码。

I attached a example of the useEffect hook implemented on your component.我附上了在您的组件上实现的 useEffect 挂钩的示例。

import React, { useState, useEffect } from "react";

export function NavItem({
  menuItem,
  panelOpened,
  setPanelOpened,
}) {
  const [categoryOpened, setCategoryOpened] = useState(false);
  
  useEffect(()=> {
    if(panelOpened) setCategoryOpened(true)
  }, [panelOpened])

  return (
    <div
      // If category is opened, should toggle a class to show / hide the children elements
      className={categoryOpened ? "opened" : "closed"}
    >
      <h2
        onClick={() => {
          // Should display the children menu items when I click the button
          setCategoryOpened(!categoryOpened);
          if (!panelOpened) {
            setPanelOpened(true);
          }
        }}
      >
        Parent Category
      </h2>

      {menuItem.children?.map((subItem) => (
        <a href={subItem.link}>
          {subItem.label}
        </a>
      ))}
    </div>
)
}

use stopPropagation(e) in onclick. React can get confused when you import 2 states.在 onclick 中使用stopPropagation(e) 。当您导入 2 个状态时,React 可能会感到困惑。 We use it to avoid this.我们用它来避免这种情况。

ep: EP:

onclick = {e => e.stopPropagation()... }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM