Show first component stack in context warning (#17922)
* Update tests * Show first component stack in context warning Co-authored-by: Dominic Gannaway <trueadm@users.noreply.github.com>
Dan Abramov committed
Jan 29, 2020 at 14:57 UTC
57333ca33a0619ff2334e4eb19139b4c7e9830f7
6 files changed
+45
-82
packages/react-reconciler/src/ReactStrictModeWarnings.js
+7
-4
@@ -324,6 +324,11 @@ if (__DEV__) {
324
ReactStrictModeWarnings.flushLegacyContextWarning = () => {
325
((pendingLegacyContextWarning: any): FiberToFiberComponentsMap).forEach(
326
(fiberArray: FiberArray, strictRoot) => {
327
+ if (fiberArray.length === 0) {
328
+ return;
329
+ }
330
+ const firstFiber = fiberArray[0];
331
+
332
const uniqueNames = new Set();
333
fiberArray.forEach(fiber => {
334
uniqueNames.add(getComponentName(fiber.type) || 'Component');
@@ -331,9 +336,7 @@ if (__DEV__) {
336
});
337
338
const sortedNames = setToSortedString(uniqueNames);
334
- const strictRootComponentStack = getStackByFiberInDevAndProd(
335
- strictRoot,
336
- );
339
+ const firstComponentStack = getStackByFiberInDevAndProd(firstFiber);
340
341
console.error(
342
'Legacy context API has been detected within a strict-mode tree.' +
@@ -343,7 +346,7 @@ if (__DEV__) {
346
'\n\nLearn more about this warning here: https://fb.me/react-legacy-context' +
347
'%s',
348
sortedNames,
346
- strictRootComponentStack,
349
+ firstComponentStack,
350
);
351
},
352
);
packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js
+24
-58
@@ -1917,7 +1917,6 @@ describe('ReactIncremental', () => {
1917
'The old API will be supported in all 16.x releases, but applications ' +
1918
'using it should migrate to the new version.\n\n' +
1919
'Please update the following components: Intl, ShowBoth, ShowLocale',
1920
- {withoutStack: true},
1920
);
1921
1922
ReactNoop.render(
@@ -1974,7 +1973,6 @@ describe('ReactIncremental', () => {
1973
'The old API will be supported in all 16.x releases, but applications ' +
1974
'using it should migrate to the new version.\n\n' +
1975
'Please update the following components: Router, ShowRoute',
1977
- {withoutStack: true},
1976
);
1977
});
1978
@@ -2000,14 +1998,11 @@ describe('ReactIncremental', () => {
1998
}
1999
2000
ReactNoop.render(<Recurse />);
2003
- expect(() =>
2004
- expect(Scheduler).toFlushWithoutYielding(),
2005
- ).toErrorDev(
2001
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2002
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2003
'The old API will be supported in all 16.x releases, but applications ' +
2004
'using it should migrate to the new version.\n\n' +
2005
'Please update the following components: Recurse',
2010
- {withoutStack: true},
2006
);
2007
expect(ops).toEqual([
2008
'Recurse {}',
@@ -2041,20 +2036,17 @@ describe('ReactIncremental', () => {
2036
};
2037
2038
ReactNoop.render(<Recurse />);
2044
- expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2045
- [
2046
- 'Warning: The <Recurse /> component appears to be a function component that returns a class instance. ' +
2047
- 'Change Recurse to a class that extends React.Component instead. ' +
2048
- "If you can't use a class try assigning the prototype on the function as a workaround. " +
2049
- '`Recurse.prototype = React.Component.prototype`. ' +
2050
- "Don't use an arrow function since it cannot be called with `new` by React.",
2051
- 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2052
- 'The old API will be supported in all 16.x releases, but applications ' +
2053
- 'using it should migrate to the new version.\n\n' +
2054
- 'Please update the following components: Recurse',
2055
- ],
2056
- {withoutStack: 1},
2057
- );
2039
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev([
2040
+ 'Warning: The <Recurse /> component appears to be a function component that returns a class instance. ' +
2041
+ 'Change Recurse to a class that extends React.Component instead. ' +
2042
+ "If you can't use a class try assigning the prototype on the function as a workaround. " +
2043
+ '`Recurse.prototype = React.Component.prototype`. ' +
2044
+ "Don't use an arrow function since it cannot be called with `new` by React.",
2045
+ 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2046
+ 'The old API will be supported in all 16.x releases, but applications ' +
2047
+ 'using it should migrate to the new version.\n\n' +
2048
+ 'Please update the following components: Recurse',
2049
+ ]);
2050
expect(ops).toEqual([
2051
'Recurse {}',
2052
'Recurse {"n":2}',
@@ -2120,7 +2112,6 @@ describe('ReactIncremental', () => {
2112
'The old API will be supported in all 16.x releases, but applications ' +
2113
'using it should migrate to the new version.\n\n' +
2114
'Please update the following components: Intl, ShowLocale',
2123
- {withoutStack: true},
2115
);
2116
});
2117
@@ -2196,14 +2187,11 @@ describe('ReactIncremental', () => {
2187
</IndirectionFn>
2188
</Intl>,
2189
);
2199
- expect(() =>
2200
- expect(Scheduler).toFlushWithoutYielding(),
2201
- ).toErrorDev(
2190
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2191
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2192
'The old API will be supported in all 16.x releases, but applications ' +
2193
'using it should migrate to the new version.\n\n' +
2194
'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2206
- {withoutStack: true},
2195
);
2196
expect(ops).toEqual([
2197
'Intl:read {}',
@@ -2292,14 +2280,11 @@ describe('ReactIncremental', () => {
2280
</IndirectionFn>
2281
</Stateful>,
2282
);
2295
- expect(() =>
2296
- expect(Scheduler).toFlushWithoutYielding(),
2297
- ).toErrorDev(
2283
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2284
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2285
'The old API will be supported in all 16.x releases, but applications ' +
2286
'using it should migrate to the new version.\n\n' +
2287
'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2302
- {withoutStack: true},
2288
);
2289
expect(ops).toEqual([
2290
'Intl:read {}',
@@ -2365,14 +2350,11 @@ describe('ReactIncremental', () => {
2350
2351
// Init
2352
ReactNoop.render(<Root />);
2368
- expect(() =>
2369
- expect(Scheduler).toFlushWithoutYielding(),
2370
- ).toErrorDev(
2353
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2354
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2355
'The old API will be supported in all 16.x releases, but applications ' +
2356
'using it should migrate to the new version.\n\n' +
2357
'Please update the following components: Child',
2375
- {withoutStack: true},
2358
);
2359
2360
// Trigger an update in the middle of the tree
@@ -2419,14 +2401,11 @@ describe('ReactIncremental', () => {
2401
2402
// Init
2403
ReactNoop.render(<Root />);
2422
- expect(() =>
2423
- expect(Scheduler).toFlushWithoutYielding(),
2424
- ).toErrorDev(
2404
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2405
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2406
'The old API will be supported in all 16.x releases, but applications ' +
2407
'using it should migrate to the new version.\n\n' +
2408
'Please update the following components: ContextProvider',
2429
- {withoutStack: true},
2409
);
2410
2411
// Trigger an update in the middle of the tree
@@ -2479,7 +2458,7 @@ describe('ReactIncremental', () => {
2458
'using it should migrate to the new version.\n\n' +
2459
'Please update the following components: MyComponent',
2460
],
2482
- {withoutStack: true},
2461
+ {withoutStack: 1},
2462
);
2463
2464
expect(ops).toEqual([
@@ -2622,14 +2601,11 @@ describe('ReactIncremental', () => {
2601
</TopContextProvider>,
2602
);
2603
2625
- expect(() =>
2626
- expect(Scheduler).toFlushWithoutYielding(),
2627
- ).toErrorDev(
2604
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2605
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2606
'The old API will be supported in all 16.x releases, but applications ' +
2607
'using it should migrate to the new version.\n\n' +
2608
'Please update the following components: Child, TopContextProvider',
2632
- {withoutStack: true},
2609
);
2610
expect(rendered).toEqual(['count:0']);
2611
instance.updateCount();
@@ -2688,14 +2664,11 @@ describe('ReactIncremental', () => {
2664
</TopContextProvider>,
2665
);
2666
2691
- expect(() =>
2692
- expect(Scheduler).toFlushWithoutYielding(),
2693
- ).toErrorDev(
2667
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2668
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2669
'The old API will be supported in all 16.x releases, but applications ' +
2670
'using it should migrate to the new version.\n\n' +
2671
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2698
- {withoutStack: true},
2672
);
2673
expect(rendered).toEqual(['count:0']);
2674
instance.updateCount();
@@ -2763,14 +2736,11 @@ describe('ReactIncremental', () => {
2736
</TopContextProvider>,
2737
);
2738
2766
- expect(() =>
2767
- expect(Scheduler).toFlushWithoutYielding(),
2768
- ).toErrorDev(
2739
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2740
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2741
'The old API will be supported in all 16.x releases, but applications ' +
2742
'using it should migrate to the new version.\n\n' +
2743
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2773
- {withoutStack: true},
2744
);
2745
expect(rendered).toEqual(['count:0']);
2746
instance.updateCount();
@@ -2848,14 +2818,11 @@ describe('ReactIncremental', () => {
2818
</TopContextProvider>,
2819
);
2820
2851
- expect(() =>
2852
- expect(Scheduler).toFlushWithoutYielding(),
2853
- ).toErrorDev(
2821
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2822
'Legacy context API has been detected within a strict-mode tree.\n\n' +
2823
'The old API will be supported in all 16.x releases, but applications ' +
2824
'using it should migrate to the new version.\n\n' +
2825
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2858
- {withoutStack: true},
2826
);
2827
expect(rendered).toEqual(['count:0, name:brian']);
2828
topInstance.updateCount();
@@ -2956,10 +2923,9 @@ describe('ReactIncremental', () => {
2923
ReactNoop.render(<Boundary />);
2924
expect(() => {
2925
expect(Scheduler).toFlushWithoutYielding();
2959
- }).toErrorDev(
2960
- ['Legacy context API has been detected within a strict-mode tree'],
2961
- {withoutStack: true},
2962
- );
2926
+ }).toErrorDev([
2927
+ 'Legacy context API has been detected within a strict-mode tree',
2928
+ ]);
2929
}
2930
2931
// First, verify that this code path normally receives Fibers as keys,
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js
+12
-18
@@ -1148,14 +1148,11 @@ describe('ReactIncrementalErrorHandling', () => {
1148
<Connector />
1149
</Provider>,
1150
);
1151
- expect(() =>
1152
- expect(Scheduler).toFlushWithoutYielding(),
1153
- ).toErrorDev(
1151
+ expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
1152
'Legacy context API has been detected within a strict-mode tree.\n\n' +
1153
'The old API will be supported in all 16.x releases, but ' +
1154
'applications using it should migrate to the new version.\n\n' +
1155
'Please update the following components: Connector, Provider',
1158
- {withoutStack: true},
1156
);
1157
1158
// If the context stack does not unwind, span will get 'abcde'
@@ -1649,19 +1646,16 @@ describe('ReactIncrementalErrorHandling', () => {
1646
ReactNoop.render(<Provider />);
1647
expect(() => {
1648
expect(Scheduler).toFlushAndThrow('Oops!');
1652
- }).toErrorDev(
1653
- [
1654
- 'Warning: The <Provider /> component appears to be a function component that returns a class instance. ' +
1655
- 'Change Provider to a class that extends React.Component instead. ' +
1656
- "If you can't use a class try assigning the prototype on the function as a workaround. " +
1657
- '`Provider.prototype = React.Component.prototype`. ' +
1658
- "Don't use an arrow function since it cannot be called with `new` by React.",
1659
- 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1660
- 'The old API will be supported in all 16.x releases, but ' +
1661
- 'applications using it should migrate to the new version.\n\n' +
1662
- 'Please update the following components: Provider',
1663
- ],
1664
- {withoutStack: 1},
1665
- );
1649
+ }).toErrorDev([
1650
+ 'Warning: The <Provider /> component appears to be a function component that returns a class instance. ' +
1651
+ 'Change Provider to a class that extends React.Component instead. ' +
1652
+ "If you can't use a class try assigning the prototype on the function as a workaround. " +
1653
+ '`Provider.prototype = React.Component.prototype`. ' +
1654
+ "Don't use an arrow function since it cannot be called with `new` by React.",
1655
+ 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1656
+ 'The old API will be supported in all 16.x releases, but ' +
1657
+ 'applications using it should migrate to the new version.\n\n' +
1658
+ 'Please update the following components: Provider',
1659
+ ]);
1660
});
1661
});
packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js
+1
-1
@@ -371,7 +371,7 @@ describe('ReactDebugFiberPerf', () => {
371
'Using UNSAFE_componentWillUpdate in strict mode is not recommended',
372
'Legacy context API has been detected within a strict-mode tree',
373
],
374
- {withoutStack: true},
374
+ {withoutStack: 3},
375
);
376
ReactNoop.render(<AllLifecycles />);
377
addComment('Update');
packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js
-1
@@ -1198,7 +1198,6 @@ describe('ReactNewContext', () => {
1198
'The old API will be supported in all 16.x releases, but applications ' +
1199
'using it should migrate to the new version.\n\n' +
1200
'Please update the following components: LegacyProvider',
1201
- {withoutStack: true},
1201
);
1202
expect(ReactNoop.getChildren()).toEqual([span('Child')]);
1203
packages/react/src/__tests__/ReactStrictMode-test.js
+1
@@ -878,6 +878,7 @@ describe('context legacy', () => {
878
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
879
'\n\nLearn more about this warning here: ' +
880
'https://fb.me/react-legacy-context' +
881
+ '\n in LegacyContextProvider (at **)' +
882
'\n in StrictMode (at **)' +
883
'\n in div (at **)' +
884
'\n in Root (at **)',