diff --git a/lib/components/Modal.js b/lib/components/Modal.js index 8e5f14c4..e41c8b4f 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -88,6 +88,8 @@ var Modal = createReactClass({ }, componentWillUnmount: function() { + if (!this.node) return; + refCount.remove(this); if (this.props.ariaHideApp) { diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js index 9dfa3850..176a2711 100644 --- a/specs/Modal.spec.js +++ b/specs/Modal.spec.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ import sinon from 'sinon'; import expect from 'expect'; -import React from 'react'; +import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import TestUtils from 'react-addons-test-utils'; import Modal from '../lib/components/Modal'; @@ -308,4 +308,37 @@ describe('State', () => { done(); }, closeTimeoutMS); }); + + it('shouldn\'t throw if forcibly unmounted during mounting', () => { + /* eslint-disable camelcase, react/prop-types */ + class Wrapper extends Component { + constructor (props) { + super(props); + this.state = { error: false }; + } + unstable_handleError () { + this.setState({ error: true }); + } + render () { + return this.state.error ? null :
{ this.props.children }
; + } + } + /* eslint-enable camelcase, react/prop-types */ + + const Throw = () => { throw new Error('reason'); }; + const TestCase = () => ( + + + + + ); + + const currentDiv = document.createElement('div'); + document.body.appendChild(currentDiv); + + const mount = () => ReactDOM.render(, currentDiv); + expect(mount).toNotThrow(); + + document.body.removeChild(currentDiv); + }); });