Skip to content

Commit

Permalink
ComponentWillUnmount should only ever be invoked once
Browse files Browse the repository at this point in the history
  • Loading branch information
jimfb authored and jim committed Apr 25, 2016
1 parent 7dbc95f commit a8e64f1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/renderers/shared/reconciler/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ var ReactCompositeComponentMixin = {

// See ReactUpdates and ReactUpdateQueue.
this._pendingCallbacks = null;

// ComponentWillUnmount shall only be called once
this._calledComponentWillUnmount = false;
},

/**
Expand Down Expand Up @@ -405,7 +408,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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1303,4 +1303,47 @@ describe('ReactCompositeComponent', function() {

});

it('should only call componentWillUnmount once', function() {
var app;
var stage = 1;
var count = 0;

class App extends React.Component {
render() {
if (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} />, container);
stage = 2;
ReactDOM.render(<App ref={setRef} />, container);
}).toThrow();
expect(count).toBe(1);
});

});

0 comments on commit a8e64f1

Please sign in to comment.