我正在尝试在React中创建一个下拉组件,当用户单击该组件时,菜单将打开,然后将为后续单击添加侦听器,这将导致其关闭。
有时候,我遇到的问题是(不是一直都有-但是我找不到源,它将不同步,并在打开后立即调用关闭,导致它从未真正出现过)是否有打开监听器的相同点击事件的原因?我尝试了event.stopPropagation(),但似乎没有帮助。
import * as React from 'react';
import {withRouter} from 'react-router-dom';
import classnames from 'classnames';
import IMenuItem from './IMenuItem';
interface IDroplistProps {
children?: any;
component?: React.ReactNode;
disabled?: boolean;
history: any;
isOpen: boolean;
items?: ReadonlyArray<IMenuItem> | ReadonlyArray<React.ReactNode>;
pullRight: boolean;
stopPropagation?: boolean;
closeDroplist(): void;
onChange(open: boolean): void;
}
const Droplist: React.FC<IDroplistProps> = ({
children,
component,
disabled,
history,
items,
pullRight,
onChange,
stopPropagation = true
}) => {
const [isOpen, setDroplistOpen] = React.useState<boolean>(false);
React.useEffect(() => {
return () => {
if (isOpen) {
closeDroplist();
}
};
}, []);
const openDroplist = (event): void => {
setDroplistOpen(true);
document.addEventListener('click', closeDroplist, false);
if (onChange) {
onChange(true);
}
};
const closeDroplist = (): void => {
setDroplistOpen(false);
document.removeEventListener('click', closeDroplist);
if (onChange) {
onChange(false);
}
};
const handleClick = (item: IMenuItem): void => {
const {onClick, to} = item;
closeDroplist();
if (to) {
history.push(to);
} else if (onClick) {
onClick();
}
};
const handleStopPropogation = (event): void => {
if (stopPropagation) {
event.stopPropagation();
}
};
const renderDroplistItems = (): ReadonlyArray<React.ReactNode> => {
const dropListItems: ReadonlyArray<any> = items;
if (items.every(React.isValidElement)) {
return dropListItems.map((item, i) => <li key={i}>{item}</li>);
}
return dropListItems.map((item , i) => <li key={i} onClick={() => handleClick(item)}>{item.text}</li>);
};
return (
<div className="dropdown" onClick={handleStopPropogation}>
<div
className="dropdown-toggle"
data-toggle="dropdown"
aria-expanded={isOpen}
onClick={openDroplist}
>
{children}
</div>
{isOpen && !disabled && (
items ? (
<ul className={classnames('dropdown-menu', {'pull-right': pullRight})}>
{renderDroplistItems()}
</ul>
) : (
component
)
)}
</div>
);
};
export default withRouter(React.memo(Droplist));