Reset instance vars before calling commit phase lifecycles (#10481)

This commit is contained in:
Andrew Clark
2017-08-17 13:52:38 -07:00
committed by GitHub
parent 072b1d9860
commit caaa0b047d
2 changed files with 45 additions and 0 deletions
@@ -66,6 +66,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
if (__DEV__) {
var callComponentWillUnmountWithTimerInDev = function(current, instance) {
startPhaseTimer(current, 'componentWillUnmount');
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
instance.componentWillUnmount();
stopPhaseTimer();
};
@@ -87,6 +89,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
} else {
try {
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
instance.componentWillUnmount();
} catch (unmountError) {
captureError(current, unmountError);
@@ -495,6 +499,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
if (__DEV__) {
startPhaseTimer(finishedWork, 'componentDidMount');
}
instance.props = finishedWork.memoizedProps;
instance.state = finishedWork.memoizedState;
instance.componentDidMount();
if (__DEV__) {
stopPhaseTimer();
@@ -505,6 +511,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
if (__DEV__) {
startPhaseTimer(finishedWork, 'componentDidUpdate');
}
instance.props = finishedWork.memoizedProps;
instance.state = finishedWork.memoizedState;
instance.componentDidUpdate(prevProps, prevState);
if (__DEV__) {
stopPhaseTimer();
@@ -1123,4 +1123,41 @@ describe('ReactIncrementalErrorHandling', () => {
);
});
});
it('resets instance variables before unmounting failed node', () => {
spyOn(console, 'error');
class ErrorBoundary extends React.Component {
state = {error: null};
componentDidCatch(error) {
this.setState({error});
}
render() {
return this.state.error ? null : this.props.children;
}
}
class Foo extends React.Component {
state = {step: 0};
componentDidMount() {
this.setState({step: 1});
}
componentWillUnmount() {
ReactNoop.yield('componentWillUnmount: ' + this.state.step);
}
render() {
ReactNoop.yield('render: ' + this.state.step);
if (this.state.step > 0) {
throw new Error('oops');
}
return null;
}
}
ReactNoop.render(<ErrorBoundary><Foo /></ErrorBoundary>);
expect(ReactNoop.flush()).toEqual([
'render: 0',
'render: 1',
'componentWillUnmount: 0',
]);
});
});