Creé un HOC para escuchar clics fuera de su componente envuelto, de modo que el componente envuelto pueda escuchar y reaccionar según sea necesario.
El HOC se ve así:
const addOutsideClickListener = (WrappedComponent) => { class wrapperComponent extends React.Component { componentDidMount() { console.log('*** component did MOUNT called ***'); document.addEventListener('click', this._handleClickOutside.bind(this), true); } componentWillUnmount() { console.log('*** component will UNMOUNT called ***'); document.removeEventListener('click', this._handleClickOutside.bind(this), true); } _handleClickOutside(e) { const domNode = ReactDOM.findDOMNode(this); if ((!domNode || !domNode.contains(e.target))) { this.wrapped.handleClickOutside(); } } render() { return ( <WrappedComponent ref={(wrapped) => { this.wrapped = wrapped }} {...this.props} /> ); } } return wrapperComponent; }Funciona bien... la mayor parte del tiempo.
Cuando se desmonta el componente envuelto, se llama al método "componentWillUnmount", pero "removeEventListener" continúa escuchando eventos, por lo que aparece el mensaje de error "Error no detectado: se llamó a findDOMNode en un componente desmontado".
Alguna idea de que puede estar causando esto ?
La razón por la que removeEventListener no funciona es porque está intentando eliminar una función recién creada. Lo mismo se aplica para addEventListener . Estas son dos funciones completamente diferentes y no tienen ninguna referencia entre sí.
Debe vincular su método _handleClickOutside para que React sepa que hay exactamente una versión del mismo. Lo haces vinculándolo en el constructor con
constructor() { super(); this._handleClickOutside.bind(this); }o vincularlo automáticamente con la metodología de flecha ES6
_handleClickOutside = (e) => { ... }Ahora pasa el método vinculado a sus eventlisteners con
document.addEventListener('click', this._handleClickOutside, true);y respectivamente el remover oyente.
Agregue esto al constructor:
this._handleClickOutside = this._handleClickOutside.bind(this)y luego haz esto:
componentDidMount() { document.addEventListener('click', this._handleClickOutside, true); } componentWillUnmount() { document.removeEventListener('click', this._handleClickOutside, true); }