Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

reactjs - Material-UI button requires 3 clicks before it will render menu

Problem summary:
This is a React app (Next.js) using Material-UI for styling components. I'm having issues with a menu button that I've created. When I click on the button to fire the menu, it takes 3 clicks before the menu will render.

Expected result:
Menu should open on the first click.

Actual result:
A working example can be seen on my website https://pdill.dev. The menu is located in the sidebar on the right side. On the first click, a small white box appears where the menu will appear, but without the menu options. The second click closes the nonexistent menu. On the third click, the menu renders.

Troubleshooting:
I tried adding a console.log() function within the handleClick function and it showed the click handler firing on the first click even though the menu doesn't render. I tried to implement a useEffect hook for the event handler, but it didn't seem to help either. It only made the event handler unreachable. My implementation may have been incorrect of course, but I'm trying to see if there's something else that I'm missing.

Code:

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:[email protected]' },
    { 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>
  )
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Issues

You construct a new list every render, but then conditionally toggle your list state between a populated list and an empty one. The behavior I see is every other time the menu is clicked it either displays the menu items or the empty white square.

Solution

Just set the anchorEl state and render the list via array mapping in the render return. No need for the isActive and list state.

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>
  );
}

Edit material-ui-button-requires-3-clicks-before-it-will-render-menu


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...