0

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.
dgg32
  • 1,409
  • 1
  • 13
  • 33
BorisL91
  • 13
  • 1
  • 3

3 Answers3

1

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?

cefn
  • 2,895
  • 19
  • 28
0

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);

};

BorisL91
  • 13
  • 1
  • 3
0

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])
jilvanx
  • 401
  • 4
  • 5