在我的React应用程序中,我正在使用材质ui中的一个popover组件。将鼠标悬停在图标上不会打开弹出窗口

时间:2019-11-14 18:40:19

标签: reactjs material-ui popover

我很难弄清楚这一点。我已经实现了一个Popover组件,其中,当用户将鼠标悬停在“ i”图标上时,将打开一个弹出窗口;当用户将鼠标悬停在该图标上时,它将关闭该弹出窗口。我认为正在发生的事情是,将鼠标悬停在图标上时,会不断调用open和close方法,因此看起来好像从未打开过。

我的组件

export const InfoIconWrapper = styled(InfoIcon)(({ theme }) => ({
  color: fade(theme.palette.black, 0.3),
}));

export const GridWrapper = styled(Grid)(({ theme }) => ({
  pointerEvents: 'none',
  padding: theme.spacing(1),
}));

const DistributionLinePopover = ({ distributionLine }) => {
  const [anchorEl, setAnchorEl] = useState(null);

  const handlePopoverOpen = event => {
    setAnchorEl(event.currentTarget);
  };

  const handlePopoverClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const mouseOverPopover = 'mouse-over-popover';
  return (
    <Fragment>
      <Typography
        aria-owns={open ? mouseOverPopover : undefined}
        aria-haspopup="true"
        onMouseEnter={handlePopoverOpen}
        onMouseOut={handlePopoverClose}
      >
        <InfoIconWrapper fontSize="small" />
      </Typography>
      <Popover
        id={mouseOverPopover}
        open={open}
        anchorEl={anchorEl}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'left',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        // onMouseOut={handlePopoverClose}
        disableRestoreFocus
      >
        <GridWrapper container>
         ...
        </GridWrapper>
      </Popover>
    </Fragment>
  );
};

如何修改此代码以使其表现出预期的效果?最初,我尝试将handlePopoverClose传递给popover,但这使得只有当您将鼠标悬停在实际的Popover而不是悬停在“ i”图标上时,弹出菜单才会关闭。

2 个答案:

答案 0 :(得分:0)

不要使anchorElem存在作为开放布尔状态值的一部分。实际上,您根本不需要检查anchorElem。处理DOM元素引用时,存在竞争条件的可能性。

我会将setAnchorEl更改为setOpen,然后在输入呼叫时将setOpen更改为true。您可能希望像一个“ X”按钮那样使用onClick事件处理程序将其设置为false。从技术上讲,我认为,当新元素呈现在您悬停的元素之上时,底层元素就会触发“鼠标移出”。参见this

According to the browser logic, the mouse cursor may be only over a single element at any time – the most nested one and top by z-index.

答案 1 :(得分:0)

好,终于找到了解决方法。

在Popover组件中,将其添加为prop:style = {{pointerEvents:'none'}} 并删除onMouseOut。

在InfoIconWrapper组件中,将其作为道具添加到onMouseLeave = {handlePopoverClose}

按预期工作:)