事件监听器调用得太早

时间:2019-03-28 03:45:57

标签: reactjs addeventlistener

我正在尝试在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));

0 个答案:

没有答案