Fix missing context to componentDidMount() when double-invoking lifecycles (#19935)
Brian Vaughn committed
Sep 30, 2020 at 15:56 UTC
7f08e908b10a58cda902611378ec053003d371ed
2 files changed
+41
-13
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+2
-13
@@ -2044,7 +2044,7 @@ function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
2044
}
2045
case ClassComponent: {
2046
const instance = fiber.stateNode;
2047
- invokeGuardedCallback(null, instance.componentDidMount, null);
2047
+ invokeGuardedCallback(null, instance.componentDidMount, instance);
2048
if (hasCaughtError()) {
2049
const mountError = clearCaughtError();
2050
captureCommitPhaseError(fiber, fiber.return, mountError);
@@ -2103,18 +2103,7 @@ function invokeLayoutEffectUnmountInDEV(fiber: Fiber): void {
2103
case ClassComponent: {
2104
const instance = fiber.stateNode;
2105
if (typeof instance.componentWillUnmount === 'function') {
2106
- invokeGuardedCallback(
2107
- null,
2108
- safelyCallComponentWillUnmount,
2109
- null,
2110
- fiber,
2111
- instance,
2112
- fiber.return,
2113
- );
2114
- if (hasCaughtError()) {
2115
- const unmountError = clearCaughtError();
2116
- captureCommitPhaseError(fiber, fiber.return, unmountError);
2117
- }
2106
+ safelyCallComponentWillUnmount(fiber, instance, fiber.return);
2107
}
2108
break;
2109
}
packages/react-reconciler/src/__tests__/ReactDoubleInvokeEvents-test.internal.js
+39
@@ -240,6 +240,45 @@ describe('ReactDoubleInvokeEvents', () => {
240
expect(Scheduler).toHaveYielded([]);
241
});
242
243
+ it('passes the right context to class component lifecycles', () => {
244
+ class App extends React.PureComponent {
245
+ test() {}
246
+
247
+ componentDidMount() {
248
+ this.test();
249
+ Scheduler.unstable_yieldValue('componentDidMount');
250
+ }
251
+
252
+ componentDidUpdate() {
253
+ this.test();
254
+ Scheduler.unstable_yieldValue('componentDidUpdate');
255
+ }
256
+
257
+ componentWillUnmount() {
258
+ this.test();
259
+ Scheduler.unstable_yieldValue('componentWillUnmount');
260
+ }
261
+
262
+ render() {
263
+ return null;
264
+ }
265
+ }
266
+
267
+ ReactNoop.act(() => {
268
+ ReactNoop.render(<App />);
269
+ });
270
+
271
+ if (__DEV__ && __VARIANT__) {
272
+ expect(Scheduler).toHaveYielded([
273
+ 'componentDidMount',
274
+ 'componentWillUnmount',
275
+ 'componentDidMount',
276
+ ]);
277
+ } else {
278
+ expect(Scheduler).toHaveYielded(['componentDidMount']);
279
+ }
280
+ });
281
+
282
it('double invoking works for class components', () => {
283
class App extends React.PureComponent {
284
componentDidMount() {