kyun
kyun

Reputation: 10264

MouseEvent target type

I have a custom hooks

const hasIgnoredClass = (element: Element, ignoredClass: string) =>
  (element.correspondingElement ? 
    element.correspondingElement : element
  ).classList.contains(ignoredClass);

const isInIgnoredElement = (element: Element, ignoredClass: string) => {
  do {
    if (hasIgnoredClass(element, ignoredClass)) {
      return true;
    }
  } while ((element = element.parentElement));
  return false;
};
function useOnClickOutside(
  refs: Array<any>, 
  handler: (e:MouseEvent | TouchEvent) => void,
  ignoreClass = 'ignore-class'
){
  React.useEffect(()=>{
    const listener = (e: MouseEvent | TouchEvent) => {
      const isValidElement = refs.some(ref => {
        if(!ref.current || ref.current.contains(e.target) || isInIgnoredElement(e.target, ignoreClass)){ return true; }
      });
      !isValidElement && handler(e);
    }
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  },[refs, handler]);

}

I've some alert

Property 'correspondingElement' does not exist on type 'Element'.ts(2339)

Type 'HTMLElement | null' is not assignable to type 'Element'. Type 'null' is not assignable to type 'Element'.ts(2322)

What is the proper type for my hook?

Upvotes: 1

Views: 1113

Answers (2)

kyun
kyun

Reputation: 10264

I think I've found an answer.

const hasIgnoredClass = (element: SVGAElement, ignoredClass: string) =>
  (element.correspondingElement ? element.correspondingElement : element).classList.contains(ignoredClass);

const isInIgnoredElement = (element: Node, ignoredClass: string) => {
  if (element === null) return;
  do {
    if (hasIgnoredClass(element as SVGAElement, ignoredClass)) {
      return true;
    }
  } while ((element = element.parentElement as Element));
  return false;
};
export default function useOnClickOutside(
  refs: Array<React.RefObject<HTMLElement>>,
  handler: (e: MouseEvent | TouchEvent) => void,
  ignoreClass = 'ignore-onClickOutside',
) {
  React.useEffect(() => {
    const listener = (e: MouseEvent | TouchEvent) => {
      const elem = e.target as Node;
      const isValidElement = refs.some(ref => {
        if (!ref.current || ref.current.contains(elem) || isInIgnoredElement(elem, ignoreClass)) {
          return true;
        }
      });
      !isValidElement && handler(e);
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [refs, handler]);
}

Upvotes: 0

Manikandan Velayutham
Manikandan Velayutham

Reputation: 2228

Not sure but try to Make e.target as Element.

const listener = (e: MouseEvent | TouchEvent) => {
 const elem = e.target as Element;
      const isValidElement = refs.some(ref => {
        if(!ref.current || ref.current.contains(e.target) || isInIgnoredElement(elem, ignoreClass)){ return true; }
      });
      !isValidElement && handler(e);
    }

Upvotes: 1

Related Questions