ComponentWillUnmount should only ever be invoked once (#6613)

This commit is contained in:
Jim
2016-04-25 18:06:30 -07:00
parent 76a4c46dba
commit 8dfdac6780
2 changed files with 46 additions and 1 deletions
@@ -132,6 +132,9 @@ var ReactCompositeComponentMixin = {
// See ReactUpdates and ReactUpdateQueue.
this._pendingCallbacks = null;
// ComponentWillUnmount shall only be called once
this._calledComponentWillUnmount = false;
},
/**
@@ -416,7 +419,8 @@ var ReactCompositeComponentMixin = {
}
var inst = this._instance;
if (inst.componentWillUnmount) {
if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
inst._calledComponentWillUnmount = true;
if (safely) {
var name = this.getName() + '.componentWillUnmount()';
ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
@@ -1303,4 +1303,45 @@ describe('ReactCompositeComponent', function() {
});
it('should only call componentWillUnmount once', function() {
var app;
var count = 0;
class App extends React.Component {
render() {
if (this.props.stage === 1) {
return <UnunmountableComponent />;
} else {
return null;
}
}
}
class UnunmountableComponent extends React.Component {
componentWillUnmount() {
app.setState({});
count++;
throw Error('always fails');
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
var container = document.createElement('div');
var setRef = (ref) => {
if (ref) {
app = ref;
}
};
expect(function() {
ReactDOM.render(<App ref={setRef} stage={1} />, container);
ReactDOM.render(<App ref={setRef} stage={2} />, container);
}).toThrow();
expect(count).toBe(1);
});
});