@samitouri / QOS-React / commits / e9aca8e389

Warn about calling setState on an unmounted component

Andrew Clark committed Feb 7, 2017 at 16:51 UTC e9aca8e389b946c45b67dbce41e738a7bec120be
4 files changed +38 -13
scripts/fiber/tests-passing-except-dev.txt
-2
@@ -57,8 +57,6 @@ src/renderers/__tests__/ReactComponentTreeHook-test.js
57 * works
58
59 src/renderers/__tests__/ReactCompositeComponent-test.js
60 -* should warn about `forceUpdate` on unmounted components
61 -* should warn about `setState` on unmounted components
60 * should warn about `setState` in render
61 * should warn about `setState` in getChildContext
62 * should disallow nested render calls
scripts/fiber/tests-passing.txt
+2
@@ -622,6 +622,8 @@ src/renderers/__tests__/ReactCompositeComponent-test.js
622 * should not pass this to getDefaultProps
623 * should use default values for undefined props
624 * should not mutate passed-in props object
625 +* should warn about `forceUpdate` on unmounted components
626 +* should warn about `setState` on unmounted components
627 * should silently allow `setState`, not call cb on unmounting components
628 * should cleanup even if render() fatals
629 * should call componentWillUnmount before unmounting
src/renderers/__tests__/ReactCompositeComponent-test.js
+18 -10
@@ -277,11 +277,15 @@ describe('ReactCompositeComponent', () => {
277
278 instance.forceUpdate();
279 expectDev(console.error.calls.count()).toBe(1);
280 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
281 - 'Warning: forceUpdate(...): Can only update a mounted or ' +
282 - 'mounting component. This usually means you called forceUpdate() on an ' +
283 - 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
284 - 'Component component.'
280 + expectDev(console.error.calls.argsFor(0)[0]).toContain(
281 + ReactDOMFeatureFlags.useFiber ?
282 + 'Can only update a mounted or mounting component. This usually means ' +
283 + 'you called setState, replaceState, or forceUpdate on an unmounted ' +
284 + 'component. This is a no-op.\n\nPlease check the code for the ' +
285 + 'Component component.' :
286 + 'Can only update a mounted or mounting component. This usually means ' +
287 + 'you called forceUpdate() on an unmounted component. This is a no-op.' +
288 + '\n\nPlease check the code for the Component component.'
289 );
290 });
291
@@ -321,11 +325,15 @@ describe('ReactCompositeComponent', () => {
325 expect(renders).toBe(2);
326
327 expectDev(console.error.calls.count()).toBe(1);
324 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
325 - 'Warning: setState(...): Can only update a mounted or ' +
326 - 'mounting component. This usually means you called setState() on an ' +
327 - 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
328 - 'Component component.'
328 + expectDev(console.error.calls.argsFor(0)[0]).toContain(
329 + ReactDOMFeatureFlags.useFiber ?
330 + 'Can only update a mounted or mounting component. This usually means ' +
331 + 'you called setState, replaceState, or forceUpdate on an unmounted ' +
332 + 'component. This is a no-op.\n\nPlease check the code for the ' +
333 + 'Component component.' :
334 + 'Can only update a mounted or mounting component. This usually means ' +
335 + 'you called setState() on an unmounted component. This is a no-op.' +
336 + '\n\nPlease check the code for the Component component.'
337 );
338 });
339
src/renderers/shared/fiber/ReactFiberScheduler.js
+18 -1
@@ -86,8 +86,21 @@ var {
86 var invariant = require('invariant');
87
88 if (__DEV__) {
89 + var warning = require('warning');
90 var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
91 var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
92 +
93 + var warnAboutUpdateOnUnmounted = function(instance : ReactClass<any>) {
94 + const ctor = instance.constructor;
95 + warning(
96 + false,
97 + 'Can only update a mounted or mounting component. This usually means ' +
98 + 'you called setState, replaceState, or forceUpdate on an unmounted ' +
99 + 'component. This is a no-op.\n\nPlease check the code for the ' +
100 + '%s component.',
101 + ctor && (ctor.displayName || ctor.name) || 'ReactClass'
102 + );
103 + };
104 }
105
106 var timeHeuristicForUnitOfWork = 1;
@@ -1137,7 +1150,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1150 return;
1151 }
1152 } else {
1140 - // TODO: Warn about setting state on an unmounted component.
1153 + if (__DEV__) {
1154 + if (fiber.tag === ClassComponent) {
1155 + warnAboutUpdateOnUnmounted(fiber.stateNode);
1156 + }
1157 + }
1158 return;
1159 }
1160 }