Reputation: 13
I have a working code which handles an outside click in my custom dropdown element.
I just can't make the TypeScript stop complaining.
It looks like this:
const nodeRef = useRef<HTMLDivElement>(null);
const handleClick = (e: MouseEvent) => {
if (nodeRef.current !== null && nodeRef.current.contains(e.target)) {
return;
}
setShowContent(false);
};
useLayoutEffect(() => {
document.addEventListener("mousedown", handleClick);
return () => {
document.removeEventListener("mousedown", handleClick);
};
}, []);
My TS Error looks like this:
Error:(58, 62) TS2345: Argument of type 'EventTarget | null' is not assignable to parameter of type 'Node | null'.
Type 'EventTarget' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 44 more.
Upvotes: 0
Views: 3590
Reputation: 461
I think this the solution, you need the callback hook. For me work and I hope the helped you
const [hidden, setHidden] = useState(true)
const dropdownRef = useRef<HTMLDivElement>(null)
const handleClickOutside = useCallback(
(e: MouseEvent) => {
if (hidden ||
(dropdownRef.current &&
dropdownRef.current.contains(e.target as HTMLElement))
) {
return
}
setHidden(!hidden)
},
[hidden]
)
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [handleClickOutside])
Upvotes: 0
Reputation: 13
I have found a solution by extracting the target and assigning it a type of HTMLElement.
That way the contains method, which expects Node | Null doesn't get confused
const target = e.target as HTMLElement;
if (nodeRef.current && nodeRef.current.contains(target)) {
return;
}
setShowContent(false);
};
Upvotes: 0
Reputation: 3321
Not all event targets are elements. Consequently the call to contains at nodeRef.current.contains(e.target)
, which strongly expects a Node, cannot be fulfilled by all the possible values which an event target could have.
This is also described at Why is Event.target not Element in Typescript?
Upvotes: 1