在 React 中打开另一个菜单时如何自动关闭一个菜单?

Posted

技术标签:

【中文标题】在 React 中打开另一个菜单时如何自动关闭一个菜单?【英文标题】:How to automaically close one menu when the other one is opened in React? 【发布时间】:2022-01-03 16:33:26 【问题描述】:

我正在工作的地方我想在其他菜单打开时自动折叠菜单。现在我已经尝试过单独使用 useState 并传递值,但它不起作用。我正在与你分享之前和之后的代码。

在 Dashboard.jsx 中,我正在映射菜单并将其作为道具传递给 MenuCards.jsx,现在如果单击 A 菜单因此是可扩展的,它会再次传递给 getExpandableMenu 并扩展菜单。 我想要的最终目标是打开一个菜单,如果单击另一个菜单,则首先关闭第一个菜单。

代码前 -

// Dashboard.tsx

 setMenuList([
        
          title: "Thermal Comfort",
          icon: thermal,
          decorator: new ManekinDecorator(IModelApp.viewManager.selectedView!),
          tooltip: "Thermal Comfort",
        ,
        
          title: "Surface Plots",
          icon: surfacePlot,
          decorator: null,
          tooltip: "Surface Plots",
        ,
        
          title: "Contour Plots",
          icon: contour,
          decorator: null,
          tooltip: "Contour Plots",
        ,
        
          title: "Comfort Cloud",
          icon: comfortCloud,
          decorator: new ComfortDecorator(),
          tooltip: "Comfort Cloud",
        ,
        
          title: "Flowlines",
          icon: flowline,
          //decorator: getFlowLineDecorator(),
          decorator: null,
          tooltip: "FlowLines",
        ,
      ]);
     else 
      setMenuList([]);
      setIsDropDownVisibal(false);
    
  , [viewPort]);

 <div className="menu">
            <div style= overflowY: "scroll", width: "inherit" >
              menuList.map((menu) => (
                <MenuCard
                  menu=menu.title
                  icon=menu.icon
                  decorator=menu.decorator
                  tooltip=menu.tooltip
                />
              ))
            </div>
          </div>

// MenuCard.tsx

const MenuCard = (props: any) => 
  const [toggle, setToggle] = React.useState(true);
  const [expandOption, setExpandOption] = React.useState(false);

  const onClick = () => 
    if (props.decorator !== null) 
      if (toggle) 
        IModelApp.viewManager.decorators.forEach((decorator) => 
          IModelApp.viewManager.dropDecorator(decorator);
        );

        IModelApp.viewManager.addDecorator(props.decorator);
       else IModelApp.viewManager.dropDecorator(props.decorator);
    
    setToggle(!toggle);
    setExpandOption(!expandOption);
  ;
  const  menu, icon, tooltip  = props;
  return (
    <div>
      <div className="mainMenu" onClick=onClick>
        <div className="icon">
          <img src=icon  className="menuIcon" />
        </div>
        <div className="menuTitle">
          <p className="title">menu</p>
        </div>
        <InfoTooltip tooltipText=tooltip />
      </div>
      expandOption && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
    </div>
  );
;

export default MenuCard;

// GetExpandedMenu.tsx

export default function GetExpandedMenu(props:any)
    const menuName = props
    const surfacePlotManager= new SurfacePlotManager()
    const contourPlotManager=new ContourPlotManager();

    switch(menuName) 
        case 'Surface Plots':
          return <SurfacePlot plotManager=surfacePlotManager/>

        case 'Thermal Comfort':
          return <ThermalComfortMenu decorator=props.decorator/>
        
        case 'Flowlines':
          return <FlowLines />

        case "Contour Plots":
          return <ContourPlot plotManager=contourPlotManager/>;
            
        case 'Comfort Cloud':
          return <ComfortCloud/>
        default:
            return <p>expanded options</p>; 
      

这是我尝试做但失败的事情。

// MenuCard.tsx
// tried making separate useState for every menu

/* eslint-disable eqeqeq */
import React from "react";
import "./MenuCard.scss";

const MenuCard = (props: any) => 
  const [toggle, setToggle] = React.useState(true);
  const [expandOption, setExpandOption] = React.useState(false);
  const [ThermalExpandOption, setThermalExpandOption] = React.useState(false);
  const [SurfaceExpandOption, setSurfaceExpandOption] = React.useState(false);
  const [ContourExpandOption, setContourExpandOption] = React.useState(false);
  const [CloudExpandOption, setCloudExpandOption] = React.useState(false);
  const [FlowlinesExpandOption, setFlowlinesExpandOption] = React.useState(false);
  

  const onClick = () => 
    console.log("Menu clicked is", props.id);
    if (props.id == 0) 
      setThermalExpandOption(!ThermalExpandOption);
      setSurfaceExpandOption(false);
      setContourExpandOption(false);
      setCloudExpandOption(false);
      setFlowlinesExpandOption(false);
     else if (props.id == 1) 
      setThermalExpandOption(false);
      setSurfaceExpandOption(!SurfaceExpandOption);
      setContourExpandOption(false);
      setCloudExpandOption(false);
      setFlowlinesExpandOption(false);
     else if (props.id == 2) 
      setThermalExpandOption(false);
      setSurfaceExpandOption(false);
      setContourExpandOption(!CloudExpandOption);
      setCloudExpandOption(false);
      setFlowlinesExpandOption(false);
     else if (props.id == 3) 
      setThermalExpandOption(false);
      setSurfaceExpandOption(false);
      setContourExpandOption(false);
      setCloudExpandOption(!CloudExpandOption);
      setFlowlinesExpandOption(false);
     if (props.id == 4) 
      setThermalExpandOption(false);
      setSurfaceExpandOption(false);
      setContourExpandOption(false);
      setCloudExpandOption(false);
      setFlowlinesExpandOption(!FlowlinesExpandOption);
     
    if (props.decorator !== null) 
      if (toggle) 
        IModelApp.viewManager.decorators.forEach((decorator) => 
          IModelApp.viewManager.dropDecorator(decorator);
        );

        IModelApp.viewManager.addDecorator(props.decorator);
       else IModelApp.viewManager.dropDecorator(props.decorator);
    
    setToggle(!toggle);
    setExpandOption(!expandOption);
  ;
  const  menu, icon, tooltip  = props;
  return (
    <div>
      <div className="mainMenu" onClick=onClick>
        <div className="icon">
          <img src=icon  className="menuIcon" />
        </div>
        <div className="menuTitle">
          <p className="title">menu</p>
        </div>
        <InfoTooltip tooltipText=tooltip />
      </div>
       ThermalExpandOption  && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
       SurfaceExpandOption  && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
       ContourExpandOption  && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
       CloudExpandOption  && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
       FlowlinesExpandOption  && (
        <GetExpandedMenu menuName=menu decorator=props.decorator />
      )
    </div>
  );
;

export default MenuCard;

【问题讨论】:

看看***.com/a/43742307/6449750 为什么这个问题的标签是react-native 【参考方案1】:

提升状态。

如果您的项目的状态取决于它旁边的菜单项的状态,您可以将两者都重构为取决于“菜单”容器中的状态。类似于“openedItem”状态。

您可以在此处的 React 文档中找到详细说明: https://reactjs.org/docs/lifting-state-up.html , 举例。

【讨论】:

以上是关于在 React 中打开另一个菜单时如何自动关闭一个菜单?的主要内容,如果未能解决你的问题,请参考以下文章

当打开一个下拉菜单时关闭另一个

打开另一个导航下拉菜单时不关闭

wpf 一个窗体中点击空白部分关闭另一个窗体

在打开另一个下拉菜单之前完全关闭一个下拉菜单

单击另一个菜单项时如何切换菜单

如何在不关闭菜单的情况下选择菜单项?