He estado creando componentes escuchando clics en todo el documento y me topé con el problema de IE11.
Escribí un par de componentes simples para reproducir este problema.
class App extends React.Component { constructor(props) { super(props); this.state = { show: false } } render() { return ( <div> <button onClick={() => this.setState({ show: !this.state.show })} > Toggle </button> <div> {this.state.show && ( <Component /> )} </div> </div> ) } } class Component extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } componentDidMount() { console.log('listener added') document.addEventListener('click', this.handleClick) } componentWillUnmount() { console.log('listener removed') document.removeEventListener('click', this.handleClick) } handleClick() { console.log('clicked!'); const node = ReactDOM.findDOMNode(this); } render() { return <div>Component</div> } } ReactDOM.render( <App /> , document.getElementById('container') ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"></div> Por lo tanto, el Component Component agrega un detector de clics al documento, y el componente App se encarga de montar y desmontar el Component .
Todo funciona perfectamente en Chrome y Firefox, cuando el Component está montado, se aplica el detector de eventos y cuando está desmontado, se elimina el detector.
Sin embargo, en IE11, cuando se elimina el oyente, la función del controlador aún se llama después y se genera un error porque intenta findDOMNode del componente desmontado. Puede que esto no sea un problema de última hora, pero aún me molesta y me gustaría saber si hay alguna solución.
Además, tenga en cuenta: detener la propagación a través event.stopPropagation no es una opción porque en mi aplicación El Component se puede desmontar de muchas maneras, el clic del botón es solo un ejemplo
Parece ser un error en IE11. Algunas opciones:
1.
Usar window.addEventListener/window.removeEventListener frente a document.addEventListener/document.removeEventListener debería funcionar.
2.
He visto otras soluciones envolver el controlador con isMounted :
if (this.isMounted) { const node = ReactDOM.findDOMNode(this); } Pero isMounted está en desuso y da una advertencia. Se considera un antipatrón .
3.
Un truco actual sería crear su propio isMounted . Algo como:
componentDidMount() { this.mounted = true; document.addEventListener('click', this.handleClick) } componentWillUnmount() { this.mounted = false; document.removeEventListener('click', this.handleClick) } handleClick() { if (this.mounted) { const node = ReactDOM.findDOMNode(this); } } Pero esto solo evita la advertencia de la consola isMounted .