You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI Styled Components中Menu锚点定位异常问题求助

解决Material UI Menu锚点定位异常问题

问题现象

点击菜单栏右侧Profile图标时,Menu未在图标下方渲染,反而出现在错误位置,控制台抛出错误:AnchorEL prop provided to the component is invalid. Anchor element should be part of the document layout。问题根源是作为锚点的IconButton被自定义Styled Component(MenuItemsBox)包裹,导致Material UI无法正确识别锚点元素的布局位置。

可行解决方案

方案1:将样式直接应用到IconButton(推荐)

把MenuItemsBox的样式直接迁移到IconButton的Styled Component上,让锚点元素本身就是IconButton,避免外层容器干扰:

// 替换原MenuItemsBox定义,直接基于IconButton创建Styled Component
const StyledActionButton = styled(IconButton)(({ theme }) => ({
  borderRadius: "10px",
  boxShadow: "1px 0px 3px 1px lightgrey",
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  background: "#c0c1c0",
}));

// 然后修改按钮渲染部分:
<StyledActionButton onClick={handleOpenProfile}>
  {" "}
  <Person />{" "}
</StyledActionButton>

这样锚点元素就是实际的IconButton,Menu能正确识别其位置,同时保留原有布局样式。

方案2:通过getPopupAnchorEl手动指定锚点

如果不想改动现有组件结构,给Menu添加getPopupAnchorEl属性,手动指定锚点为IconButton(外层MenuItemsBox的子元素):

<Menu 
  anchorEl={anchorElement} 
  open={open} 
  onClose={() => setOpen(false)}
  // 手动指定锚点为外层Box内的IconButton
  getPopupAnchorEl={() => anchorElement?.firstChild}
>
  {/* MenuItem内容不变 */}
</Menu>

方案3:使用useRef直接获取IconButton元素

给IconButton添加ref,点击时将ref指向的元素设为锚点:

const profileButtonRef = useRef(null);

const handleOpenProfile = () => {
  setAnchorElement(profileButtonRef.current);
  setOpen(true);
};

// 渲染部分
<MenuItemsBox>
  <IconButton ref={profileButtonRef} onClick={handleOpenProfile}>
    {" "}
    <Person />{" "}
  </IconButton>
</MenuItemsBox>

修改后的完整代码示例(方案1)

const Menubar = () => {
  const [anchorElement, setAnchorElement] = useState(null);
  const [open, setOpen] = useState(false);
  const navigate = useNavigate();

  const ElementsContainerBox = styled(Box)({
    display: "flex",
    gap: "15px",
    alignItems: "center",
  });

  const CustomMenuBar = styled(TextField)(({ theme }) => ({
    "& .MuiInputBase-root": {
      height: "32px",
      borderRadius: "14px",
      boxShadow: "0px 0px 3px black",
      outline: "none",
    },
  }));

  // 替换原MenuItemsBox,直接创建带样式的IconButton
  const StyledActionButton = styled(IconButton)(({ theme }) => ({
    borderRadius: "10px",
    boxShadow: "1px 0px 3px 1px lightgrey",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    background: "#c0c1c0",
  }));

  const handleOpenProfile = (e) => {
    setAnchorElement(e.currentTarget);
    setOpen(true);
  };

  return (
    <>
      <AppBar position="static">
        <Toolbar className="navbar">
          <ElementsContainerBox>
            <Box sx={{ display: { sm: "block", md: "none" } }}>
              <IconButton>
                <MenuRounded />
              </IconButton>
            </Box>

            <Box>
              <img className="auctioneer-logo" src={auctioneer_logo} />
            </Box>

            <Box>
              <CustomMenuBar
                placeholder="search"
                InputProps={{
                  startAdornment: (
                    <InputAdornment position="start">
                      {" "}
                      <Search />{" "}
                    </InputAdornment>
                  ),
                }}
              />
            </Box>
          </ElementsContainerBox>

          <ElementsContainerBox sx={{ display: { xs: "none", sm: "none", md: "flex" } }}>
            <Box>
              <Link to="/about-us" className="link-tag">
                <Typography> About us </Typography>
              </Link>
            </Box>

            <Box>
              <Link to="contact-us" className="link-tag">
                <Typography> Contact Us </Typography>
              </Link>
            </Box>

            <Box>
              <Link className="link-tag">
                <Typography> Categories </Typography>
              </Link>
            </Box>
          </ElementsContainerBox>

          <ElementsContainerBox>
            {/* 使用自定义StyledActionButton替代原MenuItemsBox+IconButton */}
            <StyledActionButton>
              {" "}
              <ShoppingBag />{" "}
            </StyledActionButton>

            <StyledActionButton onClick={handleOpenProfile}>
              {" "}
              <Person />{" "}
            </StyledActionButton>

            <IconButton sx={{ display: { xs: "block", md: "none" }, alignItems: "center" }}>
              {" "}
              <MoreVert />{" "}
            </IconButton>
          </ElementsContainerBox>
        </Toolbar>
      </AppBar>

      <Menu anchorEl={anchorElement} open={open} onClose={() => setOpen(false)}>
        <MenuItem
          onClick={() => {
            navigate("/login");
            setOpen(false);
          }}
        >
          {" "}
          Login{" "}
        </MenuItem>
        <MenuItem
          onClick={() => {
            navigate("/register");
            setOpen(false);
          }}
        >
          {" "}
          Register{" "}
        </MenuItem>
      </Menu>
    </>
  );
};

export default Menubar

内容的提问来源于stack exchange,提问作者Faiq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:17:06