@samitouri / QOS-React / commits / d8cb10f11f

Enabled warnAboutDeprecatedLifecycles flag by default (#15186)

Brian Vaughn committed Mar 27, 2019 at 16:30 UTC d8cb10f11fa0b0ab6ded66bbef86dc874b5e2d90
12 files changed +501 -456
packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.internal.js deleted
-115
@@ -1,115 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - */
9 -
10 -'use strict';
11 -
12 -let React;
13 -let ReactDOM;
14 -let ReactFeatureFlags;
15 -
16 -describe('ReactComponentLifeCycle', () => {
17 - beforeEach(() => {
18 - jest.resetModules();
19 -
20 - ReactFeatureFlags = require('shared/ReactFeatureFlags');
21 - ReactFeatureFlags.warnAboutDeprecatedLifecycles = true;
22 -
23 - React = require('react');
24 - ReactDOM = require('react-dom');
25 - });
26 -
27 - afterEach(() => {
28 - jest.resetModules();
29 - });
30 -
31 - // TODO (RFC #6) Merge this back into ReactComponentLifeCycles-test once
32 - // the 'warnAboutDeprecatedLifecycles' feature flag has been removed.
33 - it('warns about deprecated unsafe lifecycles', function() {
34 - class MyComponent extends React.Component {
35 - componentWillMount() {}
36 - componentWillReceiveProps() {}
37 - componentWillUpdate() {}
38 - render() {
39 - return null;
40 - }
41 - }
42 -
43 - const container = document.createElement('div');
44 - expect(() =>
45 - ReactDOM.render(<MyComponent x={1} />, container),
46 - ).toLowPriorityWarnDev(
47 - [
48 - 'componentWillMount is deprecated and will be removed in the next major version. ' +
49 - 'Use componentDidMount instead. As a temporary workaround, ' +
50 - 'you can rename to UNSAFE_componentWillMount.' +
51 - '\n\nPlease update the following components: MyComponent',
52 - 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' +
53 - 'Use static getDerivedStateFromProps instead.' +
54 - '\n\nPlease update the following components: MyComponent',
55 - 'componentWillUpdate is deprecated and will be removed in the next major version. ' +
56 - 'Use componentDidUpdate instead. As a temporary workaround, ' +
57 - 'you can rename to UNSAFE_componentWillUpdate.' +
58 - '\n\nPlease update the following components: MyComponent',
59 - ],
60 - {withoutStack: true},
61 - );
62 -
63 - // Dedupe check (update and instantiate new
64 - ReactDOM.render(<MyComponent x={2} />, container);
65 - ReactDOM.render(<MyComponent key="new" x={1} />, container);
66 - });
67 -
68 - describe('react-lifecycles-compat', () => {
69 - const {polyfill} = require('react-lifecycles-compat');
70 -
71 - it('should not warn for components with polyfilled getDerivedStateFromProps', () => {
72 - class PolyfilledComponent extends React.Component {
73 - state = {};
74 - static getDerivedStateFromProps() {
75 - return null;
76 - }
77 - render() {
78 - return null;
79 - }
80 - }
81 -
82 - polyfill(PolyfilledComponent);
83 -
84 - const container = document.createElement('div');
85 - ReactDOM.render(
86 - <React.StrictMode>
87 - <PolyfilledComponent />
88 - </React.StrictMode>,
89 - container,
90 - );
91 - });
92 -
93 - it('should not warn for components with polyfilled getSnapshotBeforeUpdate', () => {
94 - class PolyfilledComponent extends React.Component {
95 - getSnapshotBeforeUpdate() {
96 - return null;
97 - }
98 - componentDidUpdate() {}
99 - render() {
100 - return null;
101 - }
102 - }
103 -
104 - polyfill(PolyfilledComponent);
105 -
106 - const container = document.createElement('div');
107 - ReactDOM.render(
108 - <React.StrictMode>
109 - <PolyfilledComponent />
110 - </React.StrictMode>,
111 - container,
112 - );
113 - });
114 - });
115 -});
packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+201 -55
@@ -702,8 +702,17 @@ describe('ReactComponentLifeCycle', () => {
702 }
703
704 const container = document.createElement('div');
705 - expect(() => ReactDOM.render(<Component />, container)).toWarnDev(
706 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.',
705 + expect(() => {
706 + expect(() => ReactDOM.render(<Component />, container)).toWarnDev(
707 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.',
708 + {withoutStack: true},
709 + );
710 + }).toLowPriorityWarnDev(
711 + [
712 + 'componentWillMount is deprecated',
713 + 'componentWillReceiveProps is deprecated',
714 + 'componentWillUpdate is deprecated',
715 + ],
716 {withoutStack: true},
717 );
718 });
@@ -730,8 +739,19 @@ describe('ReactComponentLifeCycle', () => {
739 }
740
741 const container = document.createElement('div');
733 - expect(() => ReactDOM.render(<Component value={1} />, container)).toWarnDev(
734 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.',
742 + expect(() => {
743 + expect(() =>
744 + ReactDOM.render(<Component value={1} />, container),
745 + ).toWarnDev(
746 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.',
747 + {withoutStack: true},
748 + );
749 + }).toLowPriorityWarnDev(
750 + [
751 + 'componentWillMount is deprecated',
752 + 'componentWillReceiveProps is deprecated',
753 + 'componentWillUpdate is deprecated',
754 + ],
755 {withoutStack: true},
756 );
757 ReactDOM.render(<Component value={2} />, container);
@@ -781,14 +801,21 @@ describe('ReactComponentLifeCycle', () => {
801 }
802 }
803
784 - expect(() => ReactDOM.render(<AllLegacyLifecycles />, container)).toWarnDev(
785 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
786 - 'AllLegacyLifecycles uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
787 - ' componentWillMount\n' +
788 - ' UNSAFE_componentWillReceiveProps\n' +
789 - ' componentWillUpdate\n\n' +
790 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
791 - 'https://fb.me/react-async-component-lifecycle-hooks',
804 + expect(() => {
805 + expect(() =>
806 + ReactDOM.render(<AllLegacyLifecycles />, container),
807 + ).toWarnDev(
808 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
809 + 'AllLegacyLifecycles uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
810 + ' componentWillMount\n' +
811 + ' UNSAFE_componentWillReceiveProps\n' +
812 + ' componentWillUpdate\n\n' +
813 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
814 + 'https://fb.me/react-async-component-lifecycle-hooks',
815 + {withoutStack: true},
816 + );
817 + }).toLowPriorityWarnDev(
818 + ['componentWillMount is deprecated', 'componentWillUpdate is deprecated'],
819 {withoutStack: true},
820 );
821
@@ -824,15 +851,21 @@ describe('ReactComponentLifeCycle', () => {
851 }
852 }
853
827 - expect(() => ReactDOM.render(<WillMountAndUpdate />, container)).toWarnDev(
828 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
829 - 'WillMountAndUpdate uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
830 - ' componentWillMount\n' +
831 - ' UNSAFE_componentWillUpdate\n\n' +
832 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
833 - 'https://fb.me/react-async-component-lifecycle-hooks',
834 - {withoutStack: true},
835 - );
854 + expect(() => {
855 + expect(() =>
856 + ReactDOM.render(<WillMountAndUpdate />, container),
857 + ).toWarnDev(
858 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
859 + 'WillMountAndUpdate uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
860 + ' componentWillMount\n' +
861 + ' UNSAFE_componentWillUpdate\n\n' +
862 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
863 + 'https://fb.me/react-async-component-lifecycle-hooks',
864 + {withoutStack: true},
865 + );
866 + }).toLowPriorityWarnDev(['componentWillMount is deprecated'], {
867 + withoutStack: true,
868 + });
869
870 class WillReceiveProps extends React.Component {
871 state = {};
@@ -845,14 +878,18 @@ describe('ReactComponentLifeCycle', () => {
878 }
879 }
880
848 - expect(() => ReactDOM.render(<WillReceiveProps />, container)).toWarnDev(
849 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
850 - 'WillReceiveProps uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
851 - ' componentWillReceiveProps\n\n' +
852 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
853 - 'https://fb.me/react-async-component-lifecycle-hooks',
854 - {withoutStack: true},
855 - );
881 + expect(() => {
882 + expect(() => ReactDOM.render(<WillReceiveProps />, container)).toWarnDev(
883 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
884 + 'WillReceiveProps uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
885 + ' componentWillReceiveProps\n\n' +
886 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
887 + 'https://fb.me/react-async-component-lifecycle-hooks',
888 + {withoutStack: true},
889 + );
890 + }).toLowPriorityWarnDev(['componentWillReceiveProps is deprecated'], {
891 + withoutStack: true,
892 + });
893 });
894
895 it('should warn about deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', () => {
@@ -870,14 +907,21 @@ describe('ReactComponentLifeCycle', () => {
907 }
908 }
909
873 - expect(() => ReactDOM.render(<AllLegacyLifecycles />, container)).toWarnDev(
874 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
875 - 'AllLegacyLifecycles uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
876 - ' componentWillMount\n' +
877 - ' UNSAFE_componentWillReceiveProps\n' +
878 - ' componentWillUpdate\n\n' +
879 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
880 - 'https://fb.me/react-async-component-lifecycle-hooks',
910 + expect(() => {
911 + expect(() =>
912 + ReactDOM.render(<AllLegacyLifecycles />, container),
913 + ).toWarnDev(
914 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
915 + 'AllLegacyLifecycles uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
916 + ' componentWillMount\n' +
917 + ' UNSAFE_componentWillReceiveProps\n' +
918 + ' componentWillUpdate\n\n' +
919 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
920 + 'https://fb.me/react-async-component-lifecycle-hooks',
921 + {withoutStack: true},
922 + );
923 + }).toLowPriorityWarnDev(
924 + ['componentWillMount is deprecated', 'componentWillUpdate is deprecated'],
925 {withoutStack: true},
926 );
927
@@ -911,15 +955,21 @@ describe('ReactComponentLifeCycle', () => {
955 }
956 }
957
914 - expect(() => ReactDOM.render(<WillMountAndUpdate />, container)).toWarnDev(
915 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
916 - 'WillMountAndUpdate uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
917 - ' componentWillMount\n' +
918 - ' UNSAFE_componentWillUpdate\n\n' +
919 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
920 - 'https://fb.me/react-async-component-lifecycle-hooks',
921 - {withoutStack: true},
922 - );
958 + expect(() => {
959 + expect(() =>
960 + ReactDOM.render(<WillMountAndUpdate />, container),
961 + ).toWarnDev(
962 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
963 + 'WillMountAndUpdate uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
964 + ' componentWillMount\n' +
965 + ' UNSAFE_componentWillUpdate\n\n' +
966 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
967 + 'https://fb.me/react-async-component-lifecycle-hooks',
968 + {withoutStack: true},
969 + );
970 + }).toLowPriorityWarnDev(['componentWillMount is deprecated'], {
971 + withoutStack: true,
972 + });
973
974 class WillReceiveProps extends React.Component {
975 state = {};
@@ -931,14 +981,18 @@ describe('ReactComponentLifeCycle', () => {
981 }
982 }
983
934 - expect(() => ReactDOM.render(<WillReceiveProps />, container)).toWarnDev(
935 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
936 - 'WillReceiveProps uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
937 - ' componentWillReceiveProps\n\n' +
938 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
939 - 'https://fb.me/react-async-component-lifecycle-hooks',
940 - {withoutStack: true},
941 - );
984 + expect(() => {
985 + expect(() => ReactDOM.render(<WillReceiveProps />, container)).toWarnDev(
986 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
987 + 'WillReceiveProps uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
988 + ' componentWillReceiveProps\n\n' +
989 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
990 + 'https://fb.me/react-async-component-lifecycle-hooks',
991 + {withoutStack: true},
992 + );
993 + }).toLowPriorityWarnDev(['componentWillReceiveProps is deprecated'], {
994 + withoutStack: true,
995 + });
996 });
997
998 it('calls effects on module-pattern component', function() {
@@ -1072,7 +1126,16 @@ describe('ReactComponentLifeCycle', () => {
1126 }
1127
1128 const div = document.createElement('div');
1075 - ReactDOM.render(<MyComponent foo="bar" />, div);
1129 + expect(() =>
1130 + ReactDOM.render(<MyComponent foo="bar" />, div),
1131 + ).toLowPriorityWarnDev(
1132 + [
1133 + 'componentWillMount is deprecated',
1134 + 'componentWillReceiveProps is deprecated',
1135 + 'componentWillUpdate is deprecated',
1136 + ],
1137 + {withoutStack: true},
1138 + );
1139 expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);
1140
1141 log.length = 0;
@@ -1324,4 +1387,87 @@ describe('ReactComponentLifeCycle', () => {
1387 // De-duped
1388 ReactDOM.render(<MyComponent />, div);
1389 });
1390 +
1391 + it('warns about deprecated unsafe lifecycles', function() {
1392 + class MyComponent extends React.Component {
1393 + componentWillMount() {}
1394 + componentWillReceiveProps() {}
1395 + componentWillUpdate() {}
1396 + render() {
1397 + return null;
1398 + }
1399 + }
1400 +
1401 + const container = document.createElement('div');
1402 + expect(() =>
1403 + ReactDOM.render(<MyComponent x={1} />, container),
1404 + ).toLowPriorityWarnDev(
1405 + [
1406 + 'componentWillMount is deprecated and will be removed in the next major version. ' +
1407 + 'Use componentDidMount instead. As a temporary workaround, ' +
1408 + 'you can rename to UNSAFE_componentWillMount.' +
1409 + '\n\nPlease update the following components: MyComponent',
1410 + 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' +
1411 + 'Use static getDerivedStateFromProps instead.' +
1412 + '\n\nPlease update the following components: MyComponent',
1413 + 'componentWillUpdate is deprecated and will be removed in the next major version. ' +
1414 + 'Use componentDidUpdate instead. As a temporary workaround, ' +
1415 + 'you can rename to UNSAFE_componentWillUpdate.' +
1416 + '\n\nPlease update the following components: MyComponent',
1417 + ],
1418 + {withoutStack: true},
1419 + );
1420 +
1421 + // Dedupe check (update and instantiate new
1422 + ReactDOM.render(<MyComponent x={2} />, container);
1423 + ReactDOM.render(<MyComponent key="new" x={1} />, container);
1424 + });
1425 +
1426 + describe('react-lifecycles-compat', () => {
1427 + const {polyfill} = require('react-lifecycles-compat');
1428 +
1429 + it('should not warn for components with polyfilled getDerivedStateFromProps', () => {
1430 + class PolyfilledComponent extends React.Component {
1431 + state = {};
1432 + static getDerivedStateFromProps() {
1433 + return null;
1434 + }
1435 + render() {
1436 + return null;
1437 + }
1438 + }
1439 +
1440 + polyfill(PolyfilledComponent);
1441 +
1442 + const container = document.createElement('div');
1443 + ReactDOM.render(
1444 + <React.StrictMode>
1445 + <PolyfilledComponent />
1446 + </React.StrictMode>,
1447 + container,
1448 + );
1449 + });
1450 +
1451 + it('should not warn for components with polyfilled getSnapshotBeforeUpdate', () => {
1452 + class PolyfilledComponent extends React.Component {
1453 + getSnapshotBeforeUpdate() {
1454 + return null;
1455 + }
1456 + componentDidUpdate() {}
1457 + render() {
1458 + return null;
1459 + }
1460 + }
1461 +
1462 + polyfill(PolyfilledComponent);
1463 +
1464 + const container = document.createElement('div');
1465 + ReactDOM.render(
1466 + <React.StrictMode>
1467 + <PolyfilledComponent />
1468 + </React.StrictMode>,
1469 + container,
1470 + );
1471 + });
1472 + });
1473 });
packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.internal.js deleted
-120
@@ -1,120 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - */
9 -
10 -'use strict';
11 -
12 -let React;
13 -let ReactFeatureFlags;
14 -let ReactDOMServer;
15 -
16 -describe('ReactDOMServerLifecycles', () => {
17 - beforeEach(() => {
18 - ReactFeatureFlags = require('shared/ReactFeatureFlags');
19 - ReactFeatureFlags.warnAboutDeprecatedLifecycles = true;
20 -
21 - React = require('react');
22 - ReactDOMServer = require('react-dom/server');
23 - });
24 -
25 - afterEach(() => {
26 - jest.resetModules();
27 - });
28 -
29 - it('should not invoke cWM if static gDSFP is present', () => {
30 - class Component extends React.Component {
31 - state = {};
32 - static getDerivedStateFromProps() {
33 - return null;
34 - }
35 - componentWillMount() {
36 - throw Error('unexpected');
37 - }
38 - render() {
39 - return null;
40 - }
41 - }
42 -
43 - expect(() =>
44 - ReactDOMServer.renderToString(<Component />),
45 - ).toLowPriorityWarnDev(
46 - 'Component: componentWillMount() is deprecated and will be removed in the next major version.',
47 - {withoutStack: true},
48 - );
49 - });
50 -
51 - // TODO (RFC #6) Merge this back into ReactDOMServerLifecycles-test once
52 - // the 'warnAboutDeprecatedLifecycles' feature flag has been removed.
53 - it('should warn about deprecated lifecycle hooks', () => {
54 - class Component extends React.Component {
55 - componentWillMount() {}
56 - render() {
57 - return null;
58 - }
59 - }
60 -
61 - expect(() =>
62 - ReactDOMServer.renderToString(<Component />),
63 - ).toLowPriorityWarnDev(
64 - 'Warning: Component: componentWillMount() is deprecated and will be removed ' +
65 - 'in the next major version.',
66 - {withoutStack: true},
67 - );
68 -
69 - // De-duped
70 - ReactDOMServer.renderToString(<Component />);
71 - });
72 -
73 - describe('react-lifecycles-compat', () => {
74 - const {polyfill} = require('react-lifecycles-compat');
75 -
76 - it('should not warn for components with polyfilled getDerivedStateFromProps', () => {
77 - class PolyfilledComponent extends React.Component {
78 - state = {};
79 - static getDerivedStateFromProps() {
80 - return null;
81 - }
82 - render() {
83 - return null;
84 - }
85 - }
86 -
87 - polyfill(PolyfilledComponent);
88 -
89 - const container = document.createElement('div');
90 - ReactDOMServer.renderToString(
91 - <React.StrictMode>
92 - <PolyfilledComponent />
93 - </React.StrictMode>,
94 - container,
95 - );
96 - });
97 -
98 - it('should not warn for components with polyfilled getSnapshotBeforeUpdate', () => {
99 - class PolyfilledComponent extends React.Component {
100 - getSnapshotBeforeUpdate() {
101 - return null;
102 - }
103 - componentDidUpdate() {}
104 - render() {
105 - return null;
106 - }
107 - }
108 -
109 - polyfill(PolyfilledComponent);
110 -
111 - const container = document.createElement('div');
112 - ReactDOMServer.renderToString(
113 - <React.StrictMode>
114 - <PolyfilledComponent />
115 - </React.StrictMode>,
116 - container,
117 - );
118 - });
119 - });
120 -});
packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js
+95 -1
@@ -227,7 +227,11 @@ describe('ReactDOMServerLifecycles', () => {
227 }
228 }
229
230 - ReactDOMServer.renderToString(<Component />);
230 + expect(() =>
231 + ReactDOMServer.renderToString(<Component />),
232 + ).toLowPriorityWarnDev('componentWillMount() is deprecated', {
233 + withoutStack: true,
234 + });
235 expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);
236 });
237
@@ -265,4 +269,94 @@ describe('ReactDOMServerLifecycles', () => {
269 {withoutStack: true},
270 );
271 });
272 +
273 + it('should not invoke cWM if static gDSFP is present', () => {
274 + class Component extends React.Component {
275 + state = {};
276 + static getDerivedStateFromProps() {
277 + return null;
278 + }
279 + componentWillMount() {
280 + throw Error('unexpected');
281 + }
282 + render() {
283 + return null;
284 + }
285 + }
286 +
287 + expect(() =>
288 + ReactDOMServer.renderToString(<Component />),
289 + ).toLowPriorityWarnDev(
290 + 'Component: componentWillMount() is deprecated and will be removed in the next major version.',
291 + {withoutStack: true},
292 + );
293 + });
294 +
295 + it('should warn about deprecated lifecycle hooks', () => {
296 + class Component extends React.Component {
297 + componentWillMount() {}
298 + render() {
299 + return null;
300 + }
301 + }
302 +
303 + expect(() =>
304 + ReactDOMServer.renderToString(<Component />),
305 + ).toLowPriorityWarnDev(
306 + 'Warning: Component: componentWillMount() is deprecated and will be removed ' +
307 + 'in the next major version.',
308 + {withoutStack: true},
309 + );
310 +
311 + // De-duped
312 + ReactDOMServer.renderToString(<Component />);
313 + });
314 +
315 + describe('react-lifecycles-compat', () => {
316 + const {polyfill} = require('react-lifecycles-compat');
317 +
318 + it('should not warn for components with polyfilled getDerivedStateFromProps', () => {
319 + class PolyfilledComponent extends React.Component {
320 + state = {};
321 + static getDerivedStateFromProps() {
322 + return null;
323 + }
324 + render() {
325 + return null;
326 + }
327 + }
328 +
329 + polyfill(PolyfilledComponent);
330 +
331 + const container = document.createElement('div');
332 + ReactDOMServer.renderToString(
333 + <React.StrictMode>
334 + <PolyfilledComponent />
335 + </React.StrictMode>,
336 + container,
337 + );
338 + });
339 +
340 + it('should not warn for components with polyfilled getSnapshotBeforeUpdate', () => {
341 + class PolyfilledComponent extends React.Component {
342 + getSnapshotBeforeUpdate() {
343 + return null;
344 + }
345 + componentDidUpdate() {}
346 + render() {
347 + return null;
348 + }
349 + }
350 +
351 + polyfill(PolyfilledComponent);
352 +
353 + const container = document.createElement('div');
354 + ReactDOMServer.renderToString(
355 + <React.StrictMode>
356 + <PolyfilledComponent />
357 + </React.StrictMode>,
358 + container,
359 + );
360 + });
361 + });
362 });
packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
+13 -3
@@ -358,11 +358,21 @@ describe('ReactDOMServerHydration', () => {
358 );
359
360 const element = document.createElement('div');
361 - element.innerHTML = ReactDOMServer.renderToString(markup);
361 + expect(() => {
362 + element.innerHTML = ReactDOMServer.renderToString(markup);
363 + }).toLowPriorityWarnDev(
364 + ['componentWillMount() is deprecated and will be removed'],
365 + {withoutStack: true},
366 + );
367 expect(element.textContent).toBe('Hi');
368
364 - expect(() => ReactDOM.hydrate(markup, element)).toWarnDev(
365 - 'Please update the following components to use componentDidMount instead: ComponentWithWarning',
369 + expect(() => {
370 + expect(() => ReactDOM.hydrate(markup, element)).toWarnDev(
371 + 'Please update the following components to use componentDidMount instead: ComponentWithWarning',
372 + );
373 + }).toLowPriorityWarnDev(
374 + ['componentWillMount is deprecated and will be removed'],
375 + {withoutStack: true},
376 );
377 expect(element.textContent).toBe('Hi');
378 });
packages/react/src/__tests__/ReactStrictMode-test.internal.js
+45 -32
@@ -411,20 +411,29 @@ describe('ReactStrictMode', () => {
411
412 let rendered;
413
414 - expect(
415 - () => (rendered = ReactTestRenderer.create(<SyncRoot />)),
416 - ).toWarnDev(
417 - 'Unsafe lifecycle methods were found within a strict-mode tree:' +
418 - '\n in ConcurrentMode (at **)' +
419 - '\n in SyncRoot (at **)' +
420 - '\n\ncomponentWillMount: Please update the following components ' +
421 - 'to use componentDidMount instead: AsyncRoot, Parent' +
422 - '\n\ncomponentWillReceiveProps: Please update the following components ' +
423 - 'to use static getDerivedStateFromProps instead: Child, Parent' +
424 - '\n\ncomponentWillUpdate: Please update the following components ' +
425 - 'to use componentDidUpdate instead: AsyncRoot, Parent' +
426 - '\n\nLearn more about this warning here:' +
427 - '\nhttps://fb.me/react-strict-mode-warnings',
414 + expect(() => {
415 + expect(
416 + () => (rendered = ReactTestRenderer.create(<SyncRoot />)),
417 + ).toWarnDev(
418 + 'Unsafe lifecycle methods were found within a strict-mode tree:' +
419 + '\n in ConcurrentMode (at **)' +
420 + '\n in SyncRoot (at **)' +
421 + '\n\ncomponentWillMount: Please update the following components ' +
422 + 'to use componentDidMount instead: AsyncRoot, Parent' +
423 + '\n\ncomponentWillReceiveProps: Please update the following components ' +
424 + 'to use static getDerivedStateFromProps instead: Child, Parent' +
425 + '\n\ncomponentWillUpdate: Please update the following components ' +
426 + 'to use componentDidUpdate instead: AsyncRoot, Parent' +
427 + '\n\nLearn more about this warning here:' +
428 + '\nhttps://fb.me/react-strict-mode-warnings',
429 + );
430 + }).toLowPriorityWarnDev(
431 + [
432 + 'componentWillMount is deprecated',
433 + 'componentWillReceiveProps is deprecated',
434 + 'componentWillUpdate is deprecated',
435 + ],
436 + {withoutStack: true},
437 );
438
439 // Dedupe
@@ -489,24 +498,28 @@ describe('ReactStrictMode', () => {
498
499 let rendered;
500
492 - expect(
493 - () => (rendered = ReactTestRenderer.create(<SyncRoot />)),
494 - ).toWarnDev([
495 - 'Unsafe lifecycle methods were found within a strict-mode tree:' +
496 - '\n in ConcurrentMode (at **)' +
497 - '\n in AsyncRootOne (at **)' +
498 - '\n in div (at **)' +
499 - '\n in SyncRoot (at **)' +
500 - '\n\ncomponentWillMount: Please update the following components ' +
501 - 'to use componentDidMount instead: Bar, Foo',
502 - 'Unsafe lifecycle methods were found within a strict-mode tree:' +
503 - '\n in ConcurrentMode (at **)' +
504 - '\n in AsyncRootTwo (at **)' +
505 - '\n in div (at **)' +
506 - '\n in SyncRoot (at **)' +
507 - '\n\ncomponentWillMount: Please update the following components ' +
508 - 'to use componentDidMount instead: Baz',
509 - ]);
501 + expect(() => {
502 + expect(
503 + () => (rendered = ReactTestRenderer.create(<SyncRoot />)),
504 + ).toWarnDev([
505 + 'Unsafe lifecycle methods were found within a strict-mode tree:' +
506 + '\n in ConcurrentMode (at **)' +
507 + '\n in AsyncRootOne (at **)' +
508 + '\n in div (at **)' +
509 + '\n in SyncRoot (at **)' +
510 + '\n\ncomponentWillMount: Please update the following components ' +
511 + 'to use componentDidMount instead: Bar, Foo',
512 + 'Unsafe lifecycle methods were found within a strict-mode tree:' +
513 + '\n in ConcurrentMode (at **)' +
514 + '\n in AsyncRootTwo (at **)' +
515 + '\n in div (at **)' +
516 + '\n in SyncRoot (at **)' +
517 + '\n\ncomponentWillMount: Please update the following components ' +
518 + 'to use componentDidMount instead: Baz',
519 + ]);
520 + }).toLowPriorityWarnDev(['componentWillMount is deprecated'], {
521 + withoutStack: true,
522 + });
523
524 // Dedupe
525 rendered = ReactTestRenderer.create(<SyncRoot />);
packages/react/src/__tests__/createReactClassIntegration-test.internal.js
+12 -107
@@ -9,119 +9,24 @@
9
10 'use strict';
11
12 -let React;
13 -let ReactFeatureFlags;
14 -let createReactClass;
15 -
12 describe('create-react-class-integration', () => {
17 - beforeEach(() => {
18 - jest.resetModules();
19 -
20 - ReactFeatureFlags = require('shared/ReactFeatureFlags');
21 - ReactFeatureFlags.warnAboutDeprecatedLifecycles = true;
22 -
23 - React = require('react');
24 - createReactClass = require('create-react-class/factory')(
25 - React.Component,
26 - React.isValidElement,
27 - new React.Component().updater,
28 - );
29 - });
30 -
31 - // TODO (RFC #6) Merge this back into createReactClassIntegration-test once
32 - // the 'warnAboutDeprecatedLifecycles' feature flag has been removed.
33 - it('isMounted works', () => {
34 - const ReactDOM = require('react-dom');
35 -
36 - const ops = [];
37 - let instance;
38 - const Component = createReactClass({
39 - displayName: 'MyComponent',
40 - mixins: [
41 - {
42 - UNSAFE_componentWillMount() {
43 - this.log('mixin.componentWillMount');
44 - },
45 - componentDidMount() {
46 - this.log('mixin.componentDidMount');
47 - },
48 - UNSAFE_componentWillUpdate() {
49 - this.log('mixin.componentWillUpdate');
50 - },
51 - componentDidUpdate() {
52 - this.log('mixin.componentDidUpdate');
53 - },
54 - componentWillUnmount() {
55 - this.log('mixin.componentWillUnmount');
56 - },
57 - },
58 - ],
59 - log(name) {
60 - ops.push(`${name}: ${this.isMounted()}`);
61 - },
62 - getInitialState() {
63 - this.log('getInitialState');
64 - return {};
65 - },
66 - UNSAFE_componentWillMount() {
67 - this.log('componentWillMount');
68 - },
69 - componentDidMount() {
70 - this.log('componentDidMount');
71 - },
72 - UNSAFE_componentWillUpdate() {
73 - this.log('componentWillUpdate');
74 - },
75 - componentDidUpdate() {
76 - this.log('componentDidUpdate');
77 - },
78 - componentWillUnmount() {
79 - this.log('componentWillUnmount');
80 - },
81 - render() {
82 - instance = this;
83 - this.log('render');
84 - return <div />;
85 - },
86 - });
87 -
88 - const container = document.createElement('div');
89 -
90 - expect(() => ReactDOM.render(<Component />, container)).toWarnDev(
91 - 'Warning: MyComponent: isMounted is deprecated. Instead, make sure to ' +
92 - 'clean up subscriptions and pending requests in componentWillUnmount ' +
93 - 'to prevent memory leaks.',
94 - {withoutStack: true},
95 - );
96 -
97 - // Dedupe
98 - ReactDOM.render(<Component />, container);
99 -
100 - ReactDOM.unmountComponentAtNode(container);
101 - instance.log('after unmount');
102 - expect(ops).toEqual([
103 - 'getInitialState: false',
104 - 'mixin.componentWillMount: false',
105 - 'componentWillMount: false',
106 - 'render: false',
107 - 'mixin.componentDidMount: true',
108 - 'componentDidMount: true',
109 - 'mixin.componentWillUpdate: true',
110 - 'componentWillUpdate: true',
111 - 'render: true',
112 - 'mixin.componentDidUpdate: true',
113 - 'componentDidUpdate: true',
114 - 'mixin.componentWillUnmount: true',
115 - 'componentWillUnmount: true',
116 - 'after unmount: false',
117 - ]);
118 - });
119 -
13 describe('ReactNative NativeMethodsMixin', () => {
14 + let React;
15 let ReactNative;
16 let NativeMethodsMixin;
17 + let createReactClass;
18
19 beforeEach(() => {
20 + jest.resetModules();
21 +
22 + React = require('react');
23 +
24 + createReactClass = require('create-react-class/factory')(
25 + React.Component,
26 + React.isValidElement,
27 + new React.Component().updater,
28 + );
29 +
30 ReactNative = require('react-native-renderer');
31 NativeMethodsMixin =
32 ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
packages/react/src/__tests__/createReactClassIntegration-test.js
+131 -19
@@ -546,15 +546,24 @@ describe('create-react-class-integration', () => {
546 });
547
548 expect(() => {
549 - ReactDOM.render(<Component />, document.createElement('div'));
550 - }).toWarnDev(
551 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
552 - 'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
553 - ' componentWillMount\n' +
554 - ' componentWillReceiveProps\n' +
555 - ' componentWillUpdate\n\n' +
556 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
557 - 'https://fb.me/react-async-component-lifecycle-hooks',
549 + expect(() => {
550 + ReactDOM.render(<Component />, document.createElement('div'));
551 + }).toWarnDev(
552 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
553 + 'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\n' +
554 + ' componentWillMount\n' +
555 + ' componentWillReceiveProps\n' +
556 + ' componentWillUpdate\n\n' +
557 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
558 + 'https://fb.me/react-async-component-lifecycle-hooks',
559 + {withoutStack: true},
560 + );
561 + }).toLowPriorityWarnDev(
562 + [
563 + 'componentWillMount is deprecated',
564 + 'componentWillReceiveProps is deprecated',
565 + 'componentWillUpdate is deprecated',
566 + ],
567 {withoutStack: true},
568 );
569 ReactDOM.render(<Component foo={1} />, document.createElement('div'));
@@ -581,15 +590,24 @@ describe('create-react-class-integration', () => {
590 });
591
592 expect(() => {
584 - ReactDOM.render(<Component />, document.createElement('div'));
585 - }).toWarnDev(
586 - 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
587 - 'Component uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
588 - ' componentWillMount\n' +
589 - ' componentWillReceiveProps\n' +
590 - ' componentWillUpdate\n\n' +
591 - 'The above lifecycles should be removed. Learn more about this warning here:\n' +
592 - 'https://fb.me/react-async-component-lifecycle-hooks',
593 + expect(() => {
594 + ReactDOM.render(<Component />, document.createElement('div'));
595 + }).toWarnDev(
596 + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
597 + 'Component uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\n' +
598 + ' componentWillMount\n' +
599 + ' componentWillReceiveProps\n' +
600 + ' componentWillUpdate\n\n' +
601 + 'The above lifecycles should be removed. Learn more about this warning here:\n' +
602 + 'https://fb.me/react-async-component-lifecycle-hooks',
603 + {withoutStack: true},
604 + );
605 + }).toLowPriorityWarnDev(
606 + [
607 + 'componentWillMount is deprecated',
608 + 'componentWillReceiveProps is deprecated',
609 + 'componentWillUpdate is deprecated',
610 + ],
611 {withoutStack: true},
612 );
613 ReactDOM.render(<Component foo={1} />, document.createElement('div'));
@@ -627,7 +645,16 @@ describe('create-react-class-integration', () => {
645 });
646
647 const div = document.createElement('div');
630 - ReactDOM.render(<Component foo="bar" />, div);
648 + expect(() =>
649 + ReactDOM.render(<Component foo="bar" />, div),
650 + ).toLowPriorityWarnDev(
651 + [
652 + 'componentWillMount is deprecated',
653 + 'componentWillReceiveProps is deprecated',
654 + 'componentWillUpdate is deprecated',
655 + ],
656 + {withoutStack: true},
657 + );
658 expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);
659
660 log.length = 0;
@@ -640,4 +667,89 @@ describe('create-react-class-integration', () => {
667 'UNSAFE_componentWillUpdate',
668 ]);
669 });
670 +
671 + it('isMounted works', () => {
672 + const ops = [];
673 + let instance;
674 + const Component = createReactClass({
675 + displayName: 'MyComponent',
676 + mixins: [
677 + {
678 + UNSAFE_componentWillMount() {
679 + this.log('mixin.componentWillMount');
680 + },
681 + componentDidMount() {
682 + this.log('mixin.componentDidMount');
683 + },
684 + UNSAFE_componentWillUpdate() {
685 + this.log('mixin.componentWillUpdate');
686 + },
687 + componentDidUpdate() {
688 + this.log('mixin.componentDidUpdate');
689 + },
690 + componentWillUnmount() {
691 + this.log('mixin.componentWillUnmount');
692 + },
693 + },
694 + ],
695 + log(name) {
696 + ops.push(`${name}: ${this.isMounted()}`);
697 + },
698 + getInitialState() {
699 + this.log('getInitialState');
700 + return {};
701 + },
702 + UNSAFE_componentWillMount() {
703 + this.log('componentWillMount');
704 + },
705 + componentDidMount() {
706 + this.log('componentDidMount');
707 + },
708 + UNSAFE_componentWillUpdate() {
709 + this.log('componentWillUpdate');
710 + },
711 + componentDidUpdate() {
712 + this.log('componentDidUpdate');
713 + },
714 + componentWillUnmount() {
715 + this.log('componentWillUnmount');
716 + },
717 + render() {
718 + instance = this;
719 + this.log('render');
720 + return <div />;
721 + },
722 + });
723 +
724 + const container = document.createElement('div');
725 +
726 + expect(() => ReactDOM.render(<Component />, container)).toWarnDev(
727 + 'Warning: MyComponent: isMounted is deprecated. Instead, make sure to ' +
728 + 'clean up subscriptions and pending requests in componentWillUnmount ' +
729 + 'to prevent memory leaks.',
730 + {withoutStack: true},
731 + );
732 +
733 + // Dedupe
734 + ReactDOM.render(<Component />, container);
735 +
736 + ReactDOM.unmountComponentAtNode(container);
737 + instance.log('after unmount');
738 + expect(ops).toEqual([
739 + 'getInitialState: false',
740 + 'mixin.componentWillMount: false',
741 + 'componentWillMount: false',
742 + 'render: false',
743 + 'mixin.componentDidMount: true',
744 + 'componentDidMount: true',
745 + 'mixin.componentWillUpdate: true',
746 + 'componentWillUpdate: true',
747 + 'render: true',
748 + 'mixin.componentDidUpdate: true',
749 + 'componentDidUpdate: true',
750 + 'mixin.componentWillUnmount: true',
751 + 'componentWillUnmount: true',
752 + 'after unmount: false',
753 + ]);
754 + });
755 });
packages/shared/ReactFeatureFlags.js
+1 -1
@@ -23,7 +23,7 @@ export const debugRenderPhaseSideEffectsForStrictMode = __DEV__;
23 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
24
25 // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
26 -export const warnAboutDeprecatedLifecycles = false;
26 +export const warnAboutDeprecatedLifecycles = true;
27
28 // Gather advanced timing metrics for Profiler subtrees.
29 export const enableProfilerTimer = __PROFILE__;
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1 -1
@@ -16,7 +16,7 @@ export const debugRenderPhaseSideEffects = false;
16 export const debugRenderPhaseSideEffectsForStrictMode = false;
17 export const enableUserTimingAPI = __DEV__;
18 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
19 -export const warnAboutDeprecatedLifecycles = false;
19 +export const warnAboutDeprecatedLifecycles = true;
20 export const enableProfilerTimer = __PROFILE__;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
packages/shared/forks/ReactFeatureFlags.persistent.js
+1 -1
@@ -15,7 +15,7 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste
15 export const debugRenderPhaseSideEffects = false;
16 export const debugRenderPhaseSideEffectsForStrictMode = false;
17 export const enableUserTimingAPI = __DEV__;
18 -export const warnAboutDeprecatedLifecycles = false;
18 +export const warnAboutDeprecatedLifecycles = true;
19 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
20 export const enableProfilerTimer = __PROFILE__;
21 export const enableSchedulerTracing = __PROFILE__;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1 -1
@@ -15,7 +15,7 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste
15 export const debugRenderPhaseSideEffects = false;
16 export const debugRenderPhaseSideEffectsForStrictMode = false;
17 export const enableUserTimingAPI = __DEV__;
18 -export const warnAboutDeprecatedLifecycles = false;
18 +export const warnAboutDeprecatedLifecycles = true;
19 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
20 export const enableProfilerTimer = false;
21 export const enableSchedulerTracing = false;