Skip to content

Commit

Permalink
ComponentWillUnmount should only ever be invoked once (#6613)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimfb committed Apr 26, 2016
1 parent 76a4c46 commit 8dfdac6
Show file tree
Hide file tree
Showing 2 changed files with 46 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 @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

});

0 comments on commit 8dfdac6

Please sign in to comment.