【问题标题】:Material-UI button requires 3 clicks before it will render menuMaterial-UI 按钮需要单击 3 次才能呈现菜单
【发布时间】:2021-04-11 23:00:12
【问题描述】:

问题总结:
这是一个使用 Material-UI 来设置组件样式的 React 应用程序 (Next.js)。我创建的菜单按钮有问题。当我单击按钮触发菜单时,需要单击 3 次才能呈现菜单。

预期结果:
菜单应在第一次点击时打开。

实际结果:
可以在我的网站https://pdill.dev 上看到一个工作示例。菜单位于右侧的侧边栏中。第一次单击时,将出现一个小白框,该框将出现在菜单上,但没有菜单选项。第二次单击关闭不存在的菜单。第三次点击时,菜单呈现。

疑难解答:
我尝试在 handleClick 函数中添加一个 console.log() 函数,它显示单击处理程序在第一次单击时触发,即使菜单未呈现。我试图为事件处理程序实现一个 useEffect 挂钩,但它似乎也没有帮助。它只会使事件处理程序无法访问。当然,我的实现可能不正确,但我正在尝试看看是否还有其他我遗漏的东西。

代码:

export default function SimpleMenu () {
  const [anchorEl, setAnchorEl] = React.useState(null)
  const menuOptions = [
    { name: 'Home', href: 'https://pdill.dev/#top' },
    { name: 'About me', href: 'https://pdill.dev/#About' },
    { name: 'Projects', href: 'https://pdill.dev/#projects' },
    { name: 'Contact', href: 'mailto:paul@pdill.dev' },
    { name: 'Resume' }
  ]
  const [list, setList] = useState([])
  const [isActive, setIsActive] = useState(false)
  const newList = []

  const listMenuOptions = () => {
    Object.values(menuOptions).forEach((item, index) => {
      newList.push(<MenuItem key={index} onClick={handleClose}><a href={item.href}>{item.name}</a></MenuItem>)
    })
    return newList
  }

  function handleClick (event) {
    setAnchorEl(event.currentTarget)
    listMenuOptions()
    console.log(newList) //Added to show the list is firing
    setIsActive(!isActive)
    isActive ? setList(newList) : setList(null)
  }

  function handleClose () {
    setAnchorEl(null)
  }

  return (
    <div>
      <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
      ☰
      </Button>
      <Menu
        id="simple-menu"
        anchorReference="anchorEl"
        anchorEl={anchorEl}
        getContentAnchorEl={null}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'left'
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'right'
        }}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleClose}
      >
        {list}
      </Menu>
    </div>
  )
}

【问题讨论】:

  • 试试这个!isActive ? setList(newList) : setList(null)而不是isActive ? setList(newList) : setList(null)
  • 感谢您的建议!您的解决方案确实帮助菜单在第一次单击时呈现,但它仍然在每第三次单击时呈现一个白色方块。下面由 Drew Reese 提供的解决方案允许菜单在每次点击时呈现。

标签: reactjs material-ui next.js


【解决方案1】:

问题

您每次渲染都构建一个新列表,然后有条件地在填充列表和空列表之间切换list 状态。我看到的行为是每隔一次单击菜单时,它要么显示菜单项,要么显示空的白色方块。

解决方案

只需设置anchorEl 状态并通过渲染返回中的数组映射来渲染列表。不需要isActivelist 状态。

function SimpleMenu() {
  const [anchorEl, setAnchorEl] = React.useState(null);

  function handleClick(event) {
    setAnchorEl(event.currentTarget);
  }

  function handleClose() {
    setAnchorEl(null);
  }

  return (
    <div>
      <Button
        aria-controls="simple-menu"
        aria-haspopup="true"
        onClick={handleClick}
      >
        ☰
      </Button>
      <Menu
        id="simple-menu"
        anchorReference="anchorEl"
        anchorEl={anchorEl}
        getContentAnchorEl={null}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "right"
        }}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleClose}
      >
        {Object.values(menuOptions).map((item, index) => (
          <MenuItem key={index} onClick={handleClose}>
            <a href={item.href}>{item.name}</a>
          </MenuItem>
        ))}
      </Menu>
    </div>
  );
}

【讨论】:

  • 效果很好,并且简化了我的代码!感谢您的帮助,德鲁!
  • @PDill5446 太好了!如果您发现答案和解释有帮助,请不要忘记投票。干杯。
  • 昨天看到这个的时候我还没有赢得投票的特权,但是在你回复之后我现在有了。很高兴对此表示赞同!再次感谢。
猜你喜欢
  • 2022-07-01
  • 2014-08-08
  • 2017-09-23
  • 2019-05-30
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
相关资源
最近更新 更多