@samitouri / QOS-React / commits / caaa0b047d

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

Andrew Clark committed Aug 17, 2017 at 13:52 UTC caaa0b047db482bb84e8064fc1e269c8b752a784
2 files changed +45
src/renderers/shared/fiber/ReactFiberCommitWork.js
+8
@@ -66,6 +66,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
66 if (__DEV__) {
67 var callComponentWillUnmountWithTimerInDev = function(current, instance) {
68 startPhaseTimer(current, 'componentWillUnmount');
69 + instance.props = current.memoizedProps;
70 + instance.state = current.memoizedState;
71 instance.componentWillUnmount();
72 stopPhaseTimer();
73 };
@@ -87,6 +89,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
89 }
90 } else {
91 try {
92 + instance.props = current.memoizedProps;
93 + instance.state = current.memoizedState;
94 instance.componentWillUnmount();
95 } catch (unmountError) {
96 captureError(current, unmountError);
@@ -495,6 +499,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
499 if (__DEV__) {
500 startPhaseTimer(finishedWork, 'componentDidMount');
501 }
502 + instance.props = finishedWork.memoizedProps;
503 + instance.state = finishedWork.memoizedState;
504 instance.componentDidMount();
505 if (__DEV__) {
506 stopPhaseTimer();
@@ -505,6 +511,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
511 if (__DEV__) {
512 startPhaseTimer(finishedWork, 'componentDidUpdate');
513 }
514 + instance.props = finishedWork.memoizedProps;
515 + instance.state = finishedWork.memoizedState;
516 instance.componentDidUpdate(prevProps, prevState);
517 if (__DEV__) {
518 stopPhaseTimer();
src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js
+37
@@ -1123,4 +1123,41 @@ describe('ReactIncrementalErrorHandling', () => {
1123 );
1124 });
1125 });
1126 +
1127 + it('resets instance variables before unmounting failed node', () => {
1128 + spyOn(console, 'error');
1129 +
1130 + class ErrorBoundary extends React.Component {
1131 + state = {error: null};
1132 + componentDidCatch(error) {
1133 + this.setState({error});
1134 + }
1135 + render() {
1136 + return this.state.error ? null : this.props.children;
1137 + }
1138 + }
1139 + class Foo extends React.Component {
1140 + state = {step: 0};
1141 + componentDidMount() {
1142 + this.setState({step: 1});
1143 + }
1144 + componentWillUnmount() {
1145 + ReactNoop.yield('componentWillUnmount: ' + this.state.step);
1146 + }
1147 + render() {
1148 + ReactNoop.yield('render: ' + this.state.step);
1149 + if (this.state.step > 0) {
1150 + throw new Error('oops');
1151 + }
1152 + return null;
1153 + }
1154 + }
1155 +
1156 + ReactNoop.render(<ErrorBoundary><Foo /></ErrorBoundary>);
1157 + expect(ReactNoop.flush()).toEqual([
1158 + 'render: 0',
1159 + 'render: 1',
1160 + 'componentWillUnmount: 0',
1161 + ]);
1162 + });
1163 });