Javascript 自定义反应下拉菜单未正确打开或关闭

Javascript 自定义反应下拉菜单未正确打开或关闭,javascript,reactjs,menu,use-effect,Javascript,Reactjs,Menu,Use Effect,目前,我有一个表中的3行。每行有两列:文件名和按钮 文件名只是一个虚拟链接 按钮将隐藏并显示菜单 我的要求如下: 单击一个按钮,它将切换菜单。i、 e.如果prev it关闭,则应打开。如果prev打开,则关闭 当您单击此按钮时,如果其他菜单处于打开状态,则它们应处于关闭状态 每次仅打开一个菜单 git克隆、npm安装、npm启动 我有以下代码 import React, {useState, useEffect} from 'react'; function Menu({butto

目前,我有一个表中的3行。每行有两列:文件名和按钮

  • 文件名只是一个虚拟链接

  • 按钮将隐藏并显示菜单

我的要求如下:

  • 单击一个按钮,它将切换菜单。i、 e.如果prev it关闭,则应打开。如果prev打开,则关闭
  • 当您单击此按钮时,如果其他菜单处于打开状态,则它们应处于关闭状态
  • 每次仅打开一个菜单

git克隆、npm安装、npm启动

我有以下代码

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

function Menu({buttonName, menuIndex, currRowInd, setCurrRowInd}) {
  // inside menu
  const [open, setOpen] = useState(false);
  const [showMenu, setShowMenu] = useState(false);
  const menuItems = {download: 'download', view: 'view', delete: 'delete'};

  useEffect(() => {
    if (open && menuIndex === currRowInd) {
      setShowMenu(true);
    } else {
      setShowMenu(false);
    }
  }, [open, currRowInd]);

  return (
    <div>
      <button
        onClick={event => {
          // it is mouse click
          if (event.pageX !== 0 && event.pageY !== 0) {
            // toggle
            setOpen(!open);
            setCurrRowInd(menuIndex);
          }
        }}
      >
        {buttonName}
      </button>
      {showMenu && (
        <ul style={{padding: '5px', margin: '10px', border: '1px solid #ccc'}}>
          {Object.keys(menuItems).map((item, itemIndex) => {
            return (
              <li
                tabIndex="0"
                key={itemIndex}
                style={{
                  listStyle: 'none',
                  padding: '5px',
                  backgroundColor: 'blue'
                }}
              >
                {item}
              </li>
            );
          })}
        </ul>
      )}
    </div>
  );
}

function TableElement() {
  const [currRowInd, setCurrRowInd] = useState('');

  const items = [
    {
      file: 'file1',
      button: 'button1'
    },
    {
      file: 'file2',
      button: 'button2'
    },
    {
      file: 'file3',
      button: 'button3'
    }
  ];
  return (
    <table style={{borderCollapse: 'collapse', border: '1px solid black'}}>
      <tbody>
        {items.map((item, index) => {
          return (
            <tr key={index}>
              <td style={{border: '1px solid black'}}>
                <a href="#">{item.file}</a>
              </td>
              <td style={{border: '1px solid black'}}>
                <Menu
                  buttonName={item.button}
                  menuIndex={index}
                  currRowInd={currRowInd}
                  setCurrRowInd={setCurrRowInd}
                />
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

function App() {
  return (
    <>
      <TableElement />
    </>
  );
}

export default App;
import React,{useState,useffect}来自“React”;
功能菜单({buttonName,menuIndex,currRowInd,setcurrowind}){
//内部菜单
const[open,setOpen]=useState(false);
const[showMenu,setShowMenu]=使用状态(false);
const menuItems={download:'download',view:'view',delete:'delete'};
useffect(()=>{
如果(打开和菜单索引===currowind){
设置显示菜单(真);
}否则{
设置显示菜单(假);
}
},[open,Currowind]);
返回(
{
//这是鼠标点击
如果(event.pageX!==0&&event.pageY!==0){
//拨动
setOpen(!open);
设置当前索引(menuIndex);
}
}}
>
{buttonName}
{showMenu&&(
    {Object.keys(menuItems).map((项,项索引)=>{ 返回(
  • {item}
  • ); })}
)} ); } 函数TableElement(){ const[currowind,setcurrowind]=useState(“”); 常数项=[ { 文件:'file1', 按钮:“按钮1” }, { 文件:'file2', 按钮:“按钮2” }, { 文件:“file3”, 按钮:“按钮3” } ]; 返回( {items.map((项,索引)=>{ 返回( ); })} ); } 函数App(){ 返回( ); } 导出默认应用程序;
我有一个错误:

  • 点击按钮1,打开第一个菜单(好)
  • 点击按钮2,打开第二个菜单,关闭第一个菜单(好)
  • 再次单击按钮1,第二个菜单关闭(目前为止效果良好),但第一个菜单未打开

  • 有什么想法吗?

    您不需要菜单组件中的所有状态,这只会增加很多复杂性。您的问题只需移除它,并更换一些道具即可解决

    功能菜单({buttonName,showMenu,handleClick}){
    const menuItems={download:'download',view:'view',delete:'delete'};
    返回(
    {
    //这是鼠标点击
    如果(event.pageX!==0&&event.pageY!==0){
    //拨动
    handleClick();
    }
    }}
    >
    {buttonName}
    {showMenu&&(
    
      {Object.keys(menuItems).map((项,项索引)=>{ 返回(
    • {item}
    • ); })}
    )} ); } 函数TableElement(){ //数字是更好的默认值。-1永远不会匹配 const[currowind,setcurrowind]=useState(-1); 常数项=[ { 文件:'file1', 按钮:“按钮1” }, { 文件:'file2', 按钮:“按钮2” }, { 文件:“file3”, 按钮:“按钮3” } ]; 返回( {items.map((项,索引)=>{ 返回( { //拨动 如果(索引!==currowind)设置currowind(索引) else setcurrowind(-1) }} /> ); })} ); }
    您不需要菜单组件中的所有状态,这只会增加很多复杂性。您的问题只需移除它,并更换一些道具即可解决

    功能菜单({buttonName,showMenu,handleClick}){
    const menuItems={download:'download',view:'view',delete:'delete'};
    返回(
    {
    //这是鼠标点击
    如果(event.pageX!==0&&event.pageY!==0){
    //拨动
    handleClick();
    }
    }}
    >
    {buttonName}
    {showMenu&&(
    
      {Object.keys(menuItems).map((项,项索引)=>{ 返回(
    • {item}
    • ); })}
    )} ); } 函数TableElement(){ //数字是更好的默认值。-1永远不会匹配 const[currowind,setcurrowind]=useState(-1); 常数项=[ { 文件:'file1', 按钮:“按钮1” }, { 文件:'file2', 按钮:“按钮2” }, { 文件:“file3”, 按钮:“按钮3” }
    function Menu({buttonName, showMenu, handleClick}) {
      const menuItems = {download: 'download', view: 'view', delete: 'delete'};
    
      return (
        <div>
          <button
            onClick={event => {
              // it is mouse click
              if (event.pageX !== 0 && event.pageY !== 0) {
                // toggle
                handleClick();
              }
            }}
          >
            {buttonName}
          </button>
          {showMenu && (
            <ul style={{padding: '5px', margin: '10px', border: '1px solid #ccc'}}>
              {Object.keys(menuItems).map((item, itemIndex) => {
                return (
                  <li
                    tabIndex="0"
                    key={itemIndex}
                    style={{
                      listStyle: 'none',
                      padding: '5px',
                      backgroundColor: 'blue'
                    }}
                  >
                    {item}
                  </li>
                );
              })}
            </ul>
          )}
        </div>
      );
    }
    
    function TableElement() {
      // number is a better default. -1 will never match
      const [currRowInd, setCurrRowInd] = useState(-1);
    
      const items = [
        {
          file: 'file1',
          button: 'button1'
        },
        {
          file: 'file2',
          button: 'button2'
        },
        {
          file: 'file3',
          button: 'button3'
        }
      ];
      return (
        <table style={{borderCollapse: 'collapse', border: '1px solid black'}}>
          <tbody>
            {items.map((item, index) => {
              return (
                <tr key={index}>
                  <td style={{border: '1px solid black'}}>
                    <a href="#">{item.file}</a>
                  </td>
                  <td style={{border: '1px solid black'}}>
                    <Menu
                      buttonName={item.button}
                      showMenu={index === currRowInd}
                      handleClick={() => {
                        // toggle
                        if (index !== currRowInd) setCurrRowInd(index)
                        else setCurrRowInd(-1)
                      }}
                    />
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      );
    }
    
    
    import React, { useState } from 'react';
    
    const Menu = ({
      buttonName,
      menuIndex,
      opened,
      handleClickButton
    }) => {
    
      const menuItems = {
        download: 'download',
        view: 'view',
        delete: 'delete'
      };
    
      return (
        <div>
          <button onClick={(e) => handleClickButton(menuIndex, e)}>
            {buttonName}
          </button>
    
          {opened && (
            <ul style={{padding: '5px', margin: '10px', border: '1px solid #ccc'}}>
              {Object.keys(menuItems).map((item, itemIndex) => {
                return (
                  <li
                    tabIndex="0"
                    key={itemIndex}
                    style={{
                      listStyle: 'none',
                      padding: '5px',
                      backgroundColor: 'blue'
                    }}
                  >
                    {item}
                  </li>
                );
              })}
            </ul>
          )}
        </div>
      );
    }
    
    const TableElement = _ => {
      const [currRowInd, setCurrRowInd] = useState(null);
    
      const items = [
        {
          file: 'file1',
          button: 'button1'
        },
        {
          file: 'file2',
          button: 'button2'
        },
        {
          file: 'file3',
          button: 'button3'
        }
      ];
    
      const handleButtonClick = (menuIndex, e) => {
        setCurrRowInd(menuIndex);
      }
    
      return (
        <table style={{borderCollapse: 'collapse', border: '1px solid black'}}>
          <tbody>
            {items.map((item, index) => {
              return (
                <tr key={index}>
                  <td style={{border: '1px solid black'}}>
                    <a href="#">{item.file}</a>
                  </td>
                  <td style={{border: '1px solid black'}}>
                    <Menu
                      buttonName={item.button}
                      menuIndex={index}
                      opened={currRowInd === index}
                      handleClickButton={handleButtonClick}
                    />
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      );
    }
    
    const App = _ => {
      return (
        <>
          <TableElement />
        </>
      );
    }
    
    export default App;