Reputation: 10264
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
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
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