我在Navbar中有一个用material-ui / core构建的导航菜单。
我使用useRef跟踪切换菜单关闭时单击的按钮的位置。
anchorRef.current.contains(event.target)
我得到'Uncaught TypeError: anchorRef.current.contains is not a function'
。
我尝试使用'Object.values(anchorRef.current).includes(event.target)',它总是返回false。
-更新-
anchorRef.current.props对象。
withStyles {
props:{
aria-haspopup: "true"
aria-owns: undefined
children: "계정"
className: "nav-menu--btn"
onClic: f onClick()
get ref: f()
isReactWarning: true
arguments: (...)
caller: (...)
length: 0
name: "warnAboutAccessingRef"
...
}, context{...}, refs{...}, ...}
const ToggleMenuList = ({ navAdminList, navAdminItems, classes }) => {
const [activeId, setActiveId] = useState(null);
const anchorRef = useRef(null);
const handleToggle = id => {
setActiveId(id);
};
const handleClose = event => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setActiveId(null);
};
return (
<React.Fragment>
<div className={`nav-menu--admin ${classes.root}`}>
{navAdminList.map(e => (
<div key={e.id}>
<Button
ref={anchorRef}
aria-owns={activeId === e.id ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={() => handleToggle(e.id)}
>
{e.name}
</Button>
{activeId === e.id && (
<ToggleMenuItems
id={e.id}
activeId={activeId}
handleClose={handleClose}
anchorRef={anchorRef}
items={navAdminItems[e.id]}
/>
)}
</div>
))}
</div>
</React.Fragment>
);
};
export default withStyles(styles)(ToggleMenuList);
const ToggleMenuItems = ({
listId,
activeId,
handleClose,
anchorRef,
items,
}) => {
const isOpen = activeId === listId;
const leftSideMenu = activeId === 3 || activeId === 4 ? 'leftSideMenu' : '';
return (
<Popper
open={isOpen}
anchorEl={anchorRef.current}
keepMounted
transition
disablePortal
>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin:
placement === 'bottom' ? 'center top' : 'center bottom',
}}
className={`toggle-menu ${leftSideMenu}`}
>
<Paper id="menu-list-grow">
<ClickAwayListener
onClickAway={handleClose}
>
<MenuList className="toggle-menu--list">
{items.map(e => (
<MenuItem
key={e.id}
className="toggle-menu--item"
onClick={handleClose}
>
<Link
to={e.to}
className="anchor td-none c-text1 toggle-menu--link"
>
{e.name}
</Link>
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
);
};
export default ToggleMenuItems;
react: ^16.8.6
react-dom: ^16.8.6
react-router-dom: ^4.3.1
@material-ui/core: ^3.1.2
答案 0 :(得分:0)
我假设您的ToggleMenuItems
在单击时设置了全局(document
级?)事件侦听器,以在外部单击时折叠菜单。
您有一个同级按钮元素。单击您要保持菜单展开的按钮,对吗?因此,在.contains
中使用onClick
来检查是否在ToggleMenuItems
之外但在特定Button
范围内单击了我们。它不起作用的原因:<Button>
是基于类的自定义React组件,因此它在ref中返回React组件实例。而且它没有像.contains
您可以重新设计当前的方法:仅在单击Button
的情况下停止冒泡事件。它将停止ToggleMenuItems
设置的全局事件处理程序的反应。
const stopPropagation = (event) => event.stopPropagation();
const ToggleMenuList = ({ navAdminList, navAdminItems, classes }) => {
const [activeId, setActiveId] = useState(null);
const anchorRef = useRef(null);
const handleToggle = id => {
setActiveId(id);
};
const handleClose = event => {
setActiveId(null);
};
return (
<React.Fragment>
<div className={`nav-menu--admin ${classes.root}`}>
{navAdminList.map(e => (
<div key={e.id}>
<div onClick={stopPropagation}>
<Button
aria-owns={activeId === e.id ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={() => handleToggle(e.id)}
>
{e.name}
</Button>
</div>
{activeId === e.id && (
<ToggleMenuItems
id={e.id}
activeId={activeId}
handleClose={handleClose}
anchorRef={anchorRef}
items={navAdminItems[e.id]}
/>
)}
</div>
))}
</div>
</React.Fragment>
);
};
export default withStyles(styles)(ToggleMenuList);
我将stopPropagation
处理程序放在外面,因为它不依赖于任何内部变量。