BorisL91
BorisL91

Reputation: 13

Handling Mouse event inside Ref div React Hooks + Typescript

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

Answers (3)

jilvanx
jilvanx

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

BorisL91
BorisL91

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

cefn
cefn

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

Related Questions