首页 > 解决方案 > 单击子组件时关闭弹出框

问题描述

我有一个组件,我在其中渲染一个Popover组件:

// HeaderMenu.tsx

const HeaderMenu = () => {
  const ShowMenu = () => {
    return (
      <div className={classes.profile}>
        <ul>
          <Notifications />
        </ul>
        <ul>
          <li onClick={handleClose}><Link to={`/profile/${currentUserVar().id}`}>Profile</Link></li>
          <li onClick={handleClose}><Link to='/' onClick={logout}>Logout</Link></li>
        </ul>
      </div>
    );
  };

  return (
    <div>
      <Button onClick={handleClick}>
        <AccountCircleIcon className={classes.profileIcon} />
      </Button>
      <Popover
        id={id}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'left',
        }}
      >
        <ShowMenu />
      </Popover>
    </div>
  );
};

我可以onClick={handleClose}ShowMenu函数内部使用,但我也有一个嵌套组件:Notifications. 在这个组件中,我呈现了一个带有一些链接的列表:

// Notifications.tsx

<Link to={`/profile/${notification.followedUser.id}`}>{notification.followedUser.user_name}</Link>{' '}

如果单击了组件中的链接,我将如何调用组件中的handleClose函数HeaderMenu来关闭?PopoverNotifications

我可以使用 Reactive 变量来触发Notifications组件的更改(如果已单击链接)并HeaderMenu通过调用handleClose函数对组件中的更改做出反应。但我希望有更好的方法。有什么建议么?

标签: reactjsmaterial-ui

解决方案


在您的组件中添加一个onRequestClose道具:Notifications

function Notifications({ onRequestClose }) {
  return <div onClick={onRequestClose}>Notifications</div>;
}

const ShowMenu = ({ onRequestClose }) => {
  const classes = makeStyles();

  return (
    <div className={classes.profile}>
      <ul>
        <Notifications onRequestClose={onRequestClose} />
      </ul>
      <ul>
        <li onClick={onRequestClose}>
          <Link to={`/profile/1`}>Profile</Link>
        </li>
        <li onClick={onRequestClose}>
          <Link to="/" onClick={() => {}}>
            Logout
          </Link>
        </li>
      </ul>
    </div>
  );
};

在父组件中,像这样向下传递回调:

const classes = makeStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;

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

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

return (
  <div>
    <Button onClick={handleClick}>
      <AccountCircleIcon className={classes.profileIcon} />
    </Button>
    <Popover
      id={id}
      open={open}
      anchorEl={anchorEl}
      onClose={handleClose}
      anchorOrigin={{
        vertical: "bottom",
        horizontal: "left"
      }}
    >
      <ShowMenu onRequestClose={handleClose} />
    </Popover>
  </div>
);

现场演示

Codesandbox 演示


推荐阅读