Is there any way to refine an EventTarget to a Node?
Some sample code of this requirement:
import * as React from 'react';
import ReactDOM from 'react-dom';
class MyComponent extends React.Component<{}> {
handleMouseDown = (e: MouseEvent) => {
const domNode = ReactDOM.findDOMNode(this);
if (!domNode || !domNode.contains(e.currentTarget)) {
// ...
}
};
}
This produces this error as of 0.54:
7: if (!domNode || !domNode.contains(e.currentTarget)) {
^ EventTarget. This type is incompatible with the expected param type of
[LIB] static/v0.54.0/flowlib/dom.js:441: contains(other: ?Node): boolean;
^ Node
You can either check that e.currentTarget
is an instanceof Node
class MyComponent extends React.Component<{}> {
handleMouseDown = (e: MouseEvent) => {
const el = e.currentTarget;
const domNode = ReactDOM.findDOMNode(this);
if (!(domNode && el instanceof Node && domNode.contains(el))) {
// ...
}
};
}
Or you can use the classic any
escape hatch (not recommended):
class MyComponent extends React.Component<{}> {
handleMouseDown = (e: MouseEvent) => {
const domNode = ReactDOM.findDOMNode(this);
if (!domNode || !domNode.contains((e.currentTarget: any))) {
// ...
}
};
}
Great! instanceof Node
did the trick! Thank you :)
Here's hooks version I wrote, maybe someone will find it of use :)
```import { RefObject, useEffect } from 'react';
/**
const useOutsideClick = (ref: RefObject
const eventAction = (ev: Event) => {
if (ref.current && ev.target instanceof Node && !ref.current.contains(ev.target)) {
ev.preventDefault();
action();
removeGlobalListeners();
}
};
const addGlobalListeners = () => {
document.addEventListener('click', eventAction, false);
document.addEventListener('touchend', eventAction, false);
window.addEventListener('popstate', eventAction, false);
};
const removeGlobalListeners = () => {
document.removeEventListener('click', eventAction, false);
document.removeEventListener('touchend', eventAction, false);
window.removeEventListener('popstate', eventAction, false);
};
useEffect(() => {
if (state) {
addGlobalListeners();
}
return function cleanup() {
removeGlobalListeners();
};
});
};
export default useOutsideClick;
```
Most helpful comment
You can either check that
e.currentTarget
is aninstanceof Node
Or you can use the classic
any
escape hatch (not recommended):