Skip to content

Commit 8baff7e

Browse files
committed
Update legacy context warning
Fix flow
1 parent 0c04aca commit 8baff7e

File tree

6 files changed

+75
-94
lines changed

6 files changed

+75
-94
lines changed

packages/react-reconciler/src/ReactStrictModeWarnings.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ if (__DEV__) {
287287

288288
// Tracks components we have already warned about.
289289
const didWarnAboutLegacyContext = new Set();
290-
291290
ReactStrictModeWarnings.recordLegacyContextWarning = (
292291
fiber: Fiber,
293292
instance: any,
@@ -305,7 +304,6 @@ if (__DEV__) {
305304
if (didWarnAboutLegacyContext.has(fiber.type)) {
306305
return;
307306
}
308-
309307
let warningsForRoot = pendingLegacyContextWarning.get(strictRoot);
310308

311309
if (
@@ -324,26 +322,46 @@ if (__DEV__) {
324322
ReactStrictModeWarnings.flushLegacyContextWarning = () => {
325323
((pendingLegacyContextWarning: any): FiberToFiberComponentsMap).forEach(
326324
(fiberArray: FiberArray, strictRoot) => {
327-
const uniqueNames = new Set();
325+
const componentStacks = new Map();
326+
328327
fiberArray.forEach(fiber => {
329-
uniqueNames.add(getComponentName(fiber.type) || 'Component');
328+
const componentName = getComponentName(fiber.type) || 'Component';
329+
const componentStack = getStackByFiberInDevAndProd(fiber);
330+
let count = 0;
331+
if (componentStacks.has(componentStack)) {
332+
({count} = (componentStacks.get(componentStack): any));
333+
}
334+
// Increase count by 1
335+
componentStacks.set(componentStack, {
336+
count: count + 1,
337+
name: componentName,
338+
});
330339
didWarnAboutLegacyContext.add(fiber.type);
331340
});
332341

333-
const sortedNames = setToSortedString(uniqueNames);
334-
const strictRootComponentStack = getStackByFiberInDevAndProd(
335-
strictRoot,
336-
);
342+
const stacks = Array.from(componentStacks.keys());
343+
// Find the most frequently found component stack and use that
344+
let currentCount = 0;
345+
let mostFrequentStack = null;
346+
347+
for (let i = 0; i < stacks.length; i++) {
348+
const stack = stacks[i];
349+
let {count} = (componentStacks.get(stack): any);
350+
if (count > currentCount || mostFrequentStack === null) {
351+
currentCount = count;
352+
mostFrequentStack = stack;
353+
}
354+
}
337355

338356
console.error(
339357
'Legacy context API has been detected within a strict-mode tree.' +
340358
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
341359
'using it should migrate to the new version.' +
342-
'\n\nPlease update the following components: %s' +
360+
'\n\nPlease update the following component: %s' +
343361
'\n\nLearn more about this warning here: https://fb.me/react-legacy-context' +
344362
'%s',
345-
sortedNames,
346-
strictRootComponentStack,
363+
(componentStacks.get(mostFrequentStack): any).name,
364+
mostFrequentStack,
347365
);
348366
},
349367
);

packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,8 +1916,7 @@ describe('ReactIncremental', () => {
19161916
'Legacy context API has been detected within a strict-mode tree.\n\n' +
19171917
'The old API will be supported in all 16.x releases, but applications ' +
19181918
'using it should migrate to the new version.\n\n' +
1919-
'Please update the following components: Intl, ShowBoth, ShowLocale',
1920-
{withoutStack: true},
1919+
'Please update the following component: Intl',
19211920
);
19221921

19231922
ReactNoop.render(
@@ -1973,8 +1972,7 @@ describe('ReactIncremental', () => {
19731972
'Legacy context API has been detected within a strict-mode tree.\n\n' +
19741973
'The old API will be supported in all 16.x releases, but applications ' +
19751974
'using it should migrate to the new version.\n\n' +
1976-
'Please update the following components: Router, ShowRoute',
1977-
{withoutStack: true},
1975+
'Please update the following component: Router',
19781976
);
19791977
});
19801978

@@ -2000,14 +1998,11 @@ describe('ReactIncremental', () => {
20001998
}
20011999

20022000
ReactNoop.render(<Recurse />);
2003-
expect(() =>
2004-
expect(Scheduler).toFlushWithoutYielding(),
2005-
).toErrorDev(
2001+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
20062002
'Legacy context API has been detected within a strict-mode tree.\n\n' +
20072003
'The old API will be supported in all 16.x releases, but applications ' +
20082004
'using it should migrate to the new version.\n\n' +
2009-
'Please update the following components: Recurse',
2010-
{withoutStack: true},
2005+
'Please update the following component: Recurse',
20112006
);
20122007
expect(ops).toEqual([
20132008
'Recurse {}',
@@ -2051,9 +2046,9 @@ describe('ReactIncremental', () => {
20512046
'Legacy context API has been detected within a strict-mode tree.\n\n' +
20522047
'The old API will be supported in all 16.x releases, but applications ' +
20532048
'using it should migrate to the new version.\n\n' +
2054-
'Please update the following components: Recurse',
2049+
'Please update the following component: Recurse',
20552050
],
2056-
{withoutStack: 1},
2051+
{withoutStack: 0},
20572052
);
20582053
expect(ops).toEqual([
20592054
'Recurse {}',
@@ -2119,8 +2114,7 @@ describe('ReactIncremental', () => {
21192114
'Legacy context API has been detected within a strict-mode tree.\n\n' +
21202115
'The old API will be supported in all 16.x releases, but applications ' +
21212116
'using it should migrate to the new version.\n\n' +
2122-
'Please update the following components: Intl, ShowLocale',
2123-
{withoutStack: true},
2117+
'Please update the following component: Intl',
21242118
);
21252119
});
21262120

@@ -2196,14 +2190,11 @@ describe('ReactIncremental', () => {
21962190
</IndirectionFn>
21972191
</Intl>,
21982192
);
2199-
expect(() =>
2200-
expect(Scheduler).toFlushWithoutYielding(),
2201-
).toErrorDev(
2193+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
22022194
'Legacy context API has been detected within a strict-mode tree.\n\n' +
22032195
'The old API will be supported in all 16.x releases, but applications ' +
22042196
'using it should migrate to the new version.\n\n' +
2205-
'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2206-
{withoutStack: true},
2197+
'Please update the following component: Intl',
22072198
);
22082199
expect(ops).toEqual([
22092200
'Intl:read {}',
@@ -2292,14 +2283,11 @@ describe('ReactIncremental', () => {
22922283
</IndirectionFn>
22932284
</Stateful>,
22942285
);
2295-
expect(() =>
2296-
expect(Scheduler).toFlushWithoutYielding(),
2297-
).toErrorDev(
2286+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
22982287
'Legacy context API has been detected within a strict-mode tree.\n\n' +
22992288
'The old API will be supported in all 16.x releases, but applications ' +
23002289
'using it should migrate to the new version.\n\n' +
2301-
'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2302-
{withoutStack: true},
2290+
'Please update the following component: Intl',
23032291
);
23042292
expect(ops).toEqual([
23052293
'Intl:read {}',
@@ -2365,14 +2353,11 @@ describe('ReactIncremental', () => {
23652353

23662354
// Init
23672355
ReactNoop.render(<Root />);
2368-
expect(() =>
2369-
expect(Scheduler).toFlushWithoutYielding(),
2370-
).toErrorDev(
2356+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
23712357
'Legacy context API has been detected within a strict-mode tree.\n\n' +
23722358
'The old API will be supported in all 16.x releases, but applications ' +
23732359
'using it should migrate to the new version.\n\n' +
2374-
'Please update the following components: Child',
2375-
{withoutStack: true},
2360+
'Please update the following component: Child',
23762361
);
23772362

23782363
// Trigger an update in the middle of the tree
@@ -2419,14 +2404,11 @@ describe('ReactIncremental', () => {
24192404

24202405
// Init
24212406
ReactNoop.render(<Root />);
2422-
expect(() =>
2423-
expect(Scheduler).toFlushWithoutYielding(),
2424-
).toErrorDev(
2407+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
24252408
'Legacy context API has been detected within a strict-mode tree.\n\n' +
24262409
'The old API will be supported in all 16.x releases, but applications ' +
24272410
'using it should migrate to the new version.\n\n' +
2428-
'Please update the following components: ContextProvider',
2429-
{withoutStack: true},
2411+
'Please update the following component: ContextProvider',
24302412
);
24312413

24322414
// Trigger an update in the middle of the tree
@@ -2477,9 +2459,9 @@ describe('ReactIncremental', () => {
24772459
'Legacy context API has been detected within a strict-mode tree.\n\n' +
24782460
'The old API will be supported in all 16.x releases, but applications ' +
24792461
'using it should migrate to the new version.\n\n' +
2480-
'Please update the following components: MyComponent',
2462+
'Please update the following component: MyComponent',
24812463
],
2482-
{withoutStack: true},
2464+
{withoutStack: 1},
24832465
);
24842466

24852467
expect(ops).toEqual([
@@ -2622,14 +2604,11 @@ describe('ReactIncremental', () => {
26222604
</TopContextProvider>,
26232605
);
26242606

2625-
expect(() =>
2626-
expect(Scheduler).toFlushWithoutYielding(),
2627-
).toErrorDev(
2607+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
26282608
'Legacy context API has been detected within a strict-mode tree.\n\n' +
26292609
'The old API will be supported in all 16.x releases, but applications ' +
26302610
'using it should migrate to the new version.\n\n' +
2631-
'Please update the following components: Child, TopContextProvider',
2632-
{withoutStack: true},
2611+
'Please update the following component: TopContextProvider',
26332612
);
26342613
expect(rendered).toEqual(['count:0']);
26352614
instance.updateCount();
@@ -2688,14 +2667,11 @@ describe('ReactIncremental', () => {
26882667
</TopContextProvider>,
26892668
);
26902669

2691-
expect(() =>
2692-
expect(Scheduler).toFlushWithoutYielding(),
2693-
).toErrorDev(
2670+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
26942671
'Legacy context API has been detected within a strict-mode tree.\n\n' +
26952672
'The old API will be supported in all 16.x releases, but applications ' +
26962673
'using it should migrate to the new version.\n\n' +
2697-
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2698-
{withoutStack: true},
2674+
'Please update the following component: TopContextProvider',
26992675
);
27002676
expect(rendered).toEqual(['count:0']);
27012677
instance.updateCount();
@@ -2763,14 +2739,11 @@ describe('ReactIncremental', () => {
27632739
</TopContextProvider>,
27642740
);
27652741

2766-
expect(() =>
2767-
expect(Scheduler).toFlushWithoutYielding(),
2768-
).toErrorDev(
2742+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
27692743
'Legacy context API has been detected within a strict-mode tree.\n\n' +
27702744
'The old API will be supported in all 16.x releases, but applications ' +
27712745
'using it should migrate to the new version.\n\n' +
2772-
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2773-
{withoutStack: true},
2746+
'Please update the following component: TopContextProvider',
27742747
);
27752748
expect(rendered).toEqual(['count:0']);
27762749
instance.updateCount();
@@ -2848,14 +2821,11 @@ describe('ReactIncremental', () => {
28482821
</TopContextProvider>,
28492822
);
28502823

2851-
expect(() =>
2852-
expect(Scheduler).toFlushWithoutYielding(),
2853-
).toErrorDev(
2824+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
28542825
'Legacy context API has been detected within a strict-mode tree.\n\n' +
28552826
'The old API will be supported in all 16.x releases, but applications ' +
28562827
'using it should migrate to the new version.\n\n' +
2857-
'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2858-
{withoutStack: true},
2828+
'Please update the following component: TopContextProvider',
28592829
);
28602830
expect(rendered).toEqual(['count:0, name:brian']);
28612831
topInstance.updateCount();
@@ -2956,10 +2926,9 @@ describe('ReactIncremental', () => {
29562926
ReactNoop.render(<Boundary />);
29572927
expect(() => {
29582928
expect(Scheduler).toFlushWithoutYielding();
2959-
}).toErrorDev(
2960-
['Legacy context API has been detected within a strict-mode tree'],
2961-
{withoutStack: true},
2962-
);
2929+
}).toErrorDev([
2930+
'Legacy context API has been detected within a strict-mode tree',
2931+
]);
29632932
}
29642933

29652934
// First, verify that this code path normally receives Fibers as keys,

packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,14 +1148,11 @@ describe('ReactIncrementalErrorHandling', () => {
11481148
<Connector />
11491149
</Provider>,
11501150
);
1151-
expect(() =>
1152-
expect(Scheduler).toFlushWithoutYielding(),
1153-
).toErrorDev(
1151+
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
11541152
'Legacy context API has been detected within a strict-mode tree.\n\n' +
11551153
'The old API will be supported in all 16.x releases, but ' +
11561154
'applications using it should migrate to the new version.\n\n' +
1157-
'Please update the following components: Connector, Provider',
1158-
{withoutStack: true},
1155+
'Please update the following component: Provider',
11591156
);
11601157

11611158
// If the context stack does not unwind, span will get 'abcde'
@@ -1649,19 +1646,16 @@ describe('ReactIncrementalErrorHandling', () => {
16491646
ReactNoop.render(<Provider />);
16501647
expect(() => {
16511648
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 component: Provider',
1659+
]);
16661660
});
16671661
});

packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ describe('ReactDebugFiberPerf', () => {
371371
'Using UNSAFE_componentWillUpdate in strict mode is not recommended',
372372
'Legacy context API has been detected within a strict-mode tree',
373373
],
374-
{withoutStack: true},
374+
{withoutStack: 3},
375375
);
376376
ReactNoop.render(<AllLifecycles />);
377377
addComment('Update');

packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,8 +1197,7 @@ describe('ReactNewContext', () => {
11971197
'Legacy context API has been detected within a strict-mode tree.\n\n' +
11981198
'The old API will be supported in all 16.x releases, but applications ' +
11991199
'using it should migrate to the new version.\n\n' +
1200-
'Please update the following components: LegacyProvider',
1201-
{withoutStack: true},
1200+
'Please update the following component: LegacyProvider',
12021201
);
12031202
expect(ReactNoop.getChildren()).toEqual([span('Child')]);
12041203

packages/react/src/__tests__/ReactStrictMode-test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,10 +874,11 @@ describe('context legacy', () => {
874874
'Warning: Legacy context API has been detected within a strict-mode tree.' +
875875
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
876876
'using it should migrate to the new version.' +
877-
'\n\nPlease update the following components: ' +
878-
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
877+
'\n\nPlease update the following component: ' +
878+
'LegacyContextProvider' +
879879
'\n\nLearn more about this warning here: ' +
880880
'https://fb.me/react-legacy-context' +
881+
'\n in LegacyContextProvider (at **)' +
881882
'\n in StrictMode (at **)' +
882883
'\n in div (at **)' +
883884
'\n in Root (at **)',

0 commit comments

Comments
 (0)