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;