Skip to content

Commit 24b0d33

Browse files
committed
Switch <Context> to mean <Context.Provider>
1 parent 8f79744 commit 24b0d33

23 files changed

+113
-484
lines changed

packages/react-client/src/ReactFlightReplyClient.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type {
1818
import {
1919
REACT_ELEMENT_TYPE,
2020
REACT_LAZY_TYPE,
21-
REACT_PROVIDER_TYPE,
21+
REACT_CONTEXT_TYPE,
2222
getIteratorFn,
2323
} from 'shared/ReactSymbols';
2424

@@ -297,7 +297,7 @@ export function processReply(
297297
'React Lazy cannot be passed to Server Functions from the Client.%s',
298298
describeObjectForErrorMessage(parent, key),
299299
);
300-
} else if ((value: any).$$typeof === REACT_PROVIDER_TYPE) {
300+
} else if ((value: any).$$typeof === REACT_CONTEXT_TYPE) {
301301
console.error(
302302
'React Context Providers cannot be passed to Server Functions from the Client.%s',
303303
describeObjectForErrorMessage(parent, key),

packages/react-debug-tools/src/ReactDebugHooks.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
* @flow
88
*/
99

10-
import type {
11-
ReactContext,
12-
ReactProviderType,
13-
StartTransitionOptions,
14-
} from 'shared/ReactTypes';
10+
import type {ReactContext, StartTransitionOptions} from 'shared/ReactTypes';
1511
import type {
1612
Fiber,
1713
Dispatcher as DispatcherType,
@@ -771,8 +767,7 @@ function setupContexts(contextMap: Map<ReactContext<any>, any>, fiber: Fiber) {
771767
let current: null | Fiber = fiber;
772768
while (current) {
773769
if (current.tag === ContextProvider) {
774-
const providerType: ReactProviderType<any> = current.type;
775-
const context: ReactContext<any> = providerType._context;
770+
const context: ReactContext<any> = current.type;
776771
if (!contextMap.has(context)) {
777772
// Store the current value that we're going to restore later.
778773
contextMap.set(context, context._currentValue);

packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js

+21-108
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ function initModules() {
3333
};
3434
}
3535

36-
const {resetModules, itRenders, clientRenderOnBadMarkup} =
37-
ReactDOMServerIntegrationUtils(initModules);
36+
const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);
3837

3938
describe('ReactDOMServerIntegration', () => {
4039
beforeEach(() => {
@@ -298,115 +297,29 @@ describe('ReactDOMServerIntegration', () => {
298297
expect(e.querySelector('#language3').textContent).toBe('french');
299298
});
300299

301-
itRenders(
302-
'should warn with an error message when using Context as consumer in DEV',
303-
async render => {
304-
const Theme = React.createContext('dark');
305-
const Language = React.createContext('french');
306-
307-
const App = () => (
308-
<div>
309-
<Theme.Provider value="light">
310-
<Language.Provider value="english">
311-
<Theme.Provider value="dark">
312-
<Theme>{theme => <div id="theme1">{theme}</div>}</Theme>
313-
</Theme.Provider>
314-
</Language.Provider>
315-
</Theme.Provider>
316-
</div>
317-
);
318-
// We expect 1 error.
319-
await render(<App />, 1);
320-
},
321-
);
322-
323-
// False positive regression test.
324-
itRenders(
325-
'should not warn when using Consumer from React < 16.6 with newer renderer',
326-
async render => {
327-
const Theme = React.createContext('dark');
328-
const Language = React.createContext('french');
329-
// React 16.5 and earlier didn't have a separate object.
330-
Theme.Consumer = Theme;
331-
332-
const App = () => (
333-
<div>
334-
<Theme.Provider value="light">
335-
<Language.Provider value="english">
336-
<Theme.Provider value="dark">
337-
<Theme>{theme => <div id="theme1">{theme}</div>}</Theme>
338-
</Theme.Provider>
339-
</Language.Provider>
340-
</Theme.Provider>
341-
</div>
342-
);
343-
// We expect 0 errors.
344-
await render(<App />, 0);
345-
},
346-
);
347-
348-
itRenders(
349-
'should warn with an error message when using nested context consumers in DEV',
350-
async render => {
351-
const App = () => {
352-
const Theme = React.createContext('dark');
353-
const Language = React.createContext('french');
300+
itRenders('should treat Context as Context.Provider', async render => {
301+
const Theme = React.createContext('dark');
302+
const Language = React.createContext('french');
354303

355-
return (
356-
<div>
357-
<Theme.Provider value="light">
358-
<Language.Provider value="english">
359-
<Theme.Provider value="dark">
360-
<Theme.Consumer.Consumer>
361-
{theme => <div id="theme1">{theme}</div>}
362-
</Theme.Consumer.Consumer>
363-
</Theme.Provider>
364-
</Language.Provider>
365-
</Theme.Provider>
366-
</div>
367-
);
368-
};
369-
await render(
370-
<App />,
371-
render === clientRenderOnBadMarkup
372-
? // On hydration mismatch we retry and therefore log the warning again.
373-
2
374-
: 1,
375-
);
376-
},
377-
);
304+
expect(Theme.Provider).toBe(Theme);
378305

379-
itRenders(
380-
'should warn with an error message when using Context.Consumer.Provider DEV',
381-
async render => {
382-
const App = () => {
383-
const Theme = React.createContext('dark');
384-
const Language = React.createContext('french');
306+
const App = () => (
307+
<div>
308+
<Theme value="light">
309+
<Language value="english">
310+
<Theme value="dark">
311+
<Theme.Consumer>
312+
{theme => <div id="theme1">{theme}</div>}
313+
</Theme.Consumer>
314+
</Theme>
315+
</Language>
316+
</Theme>
317+
</div>
318+
);
385319

386-
return (
387-
<div>
388-
<Theme.Provider value="light">
389-
<Language.Provider value="english">
390-
<Theme.Consumer.Provider value="dark">
391-
<Theme.Consumer>
392-
{theme => <div id="theme1">{theme}</div>}
393-
</Theme.Consumer>
394-
</Theme.Consumer.Provider>
395-
</Language.Provider>
396-
</Theme.Provider>
397-
</div>
398-
);
399-
};
400-
401-
await render(
402-
<App />,
403-
render === clientRenderOnBadMarkup
404-
? // On hydration mismatch we retry and therefore log the warning again.
405-
2
406-
: 1,
407-
);
408-
},
409-
);
320+
const e = await render(<App />, 0);
321+
expect(e.textContent).toBe('dark');
322+
});
410323

411324
it('does not pollute parallel node streams', () => {
412325
const LoggedInUser = React.createContext();

packages/react-dom/src/__tests__/ReactServerRendering-test.js

+8-15
Original file line numberDiff line numberDiff line change
@@ -1003,20 +1003,12 @@ describe('ReactDOMServer', () => {
10031003

10041004
it('should warn if an invalid contextType is defined', () => {
10051005
const Context = React.createContext();
1006-
10071006
class ComponentA extends React.Component {
1008-
// It should warn for both Context.Consumer and Context.Provider
10091007
static contextType = Context.Consumer;
10101008
render() {
10111009
return <div />;
10121010
}
10131011
}
1014-
class ComponentB extends React.Component {
1015-
static contextType = Context.Provider;
1016-
render() {
1017-
return <div />;
1018-
}
1019-
}
10201012

10211013
expect(() => {
10221014
ReactDOMServer.renderToString(<ComponentA />);
@@ -1029,13 +1021,14 @@ describe('ReactDOMServer', () => {
10291021
// Warnings should be deduped by component type
10301022
ReactDOMServer.renderToString(<ComponentA />);
10311023

1032-
expect(() => {
1033-
ReactDOMServer.renderToString(<ComponentB />);
1034-
}).toErrorDev(
1035-
'Warning: ComponentB defines an invalid contextType. ' +
1036-
'contextType should point to the Context object returned by React.createContext(). ' +
1037-
'Did you accidentally pass the Context.Provider instead?',
1038-
);
1024+
class ComponentB extends React.Component {
1025+
static contextType = Context.Provider;
1026+
render() {
1027+
return <div />;
1028+
}
1029+
}
1030+
// Does not warn because Context === Context.Provider.
1031+
ReactDOMServer.renderToString(<ComponentB />);
10391032
});
10401033

10411034
it('should not warn when class contextType is null', () => {

packages/react-is/src/ReactIs.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
REACT_MEMO_TYPE,
1919
REACT_PORTAL_TYPE,
2020
REACT_PROFILER_TYPE,
21-
REACT_PROVIDER_TYPE,
21+
REACT_CONSUMER_TYPE,
2222
REACT_STRICT_MODE_TYPE,
2323
REACT_SUSPENSE_TYPE,
2424
REACT_SUSPENSE_LIST_TYPE,
@@ -47,7 +47,7 @@ export function typeOf(object: any): mixed {
4747
case REACT_FORWARD_REF_TYPE:
4848
case REACT_LAZY_TYPE:
4949
case REACT_MEMO_TYPE:
50-
case REACT_PROVIDER_TYPE:
50+
case REACT_CONSUMER_TYPE:
5151
return $$typeofType;
5252
default:
5353
return $$typeof;
@@ -61,8 +61,8 @@ export function typeOf(object: any): mixed {
6161
return undefined;
6262
}
6363

64-
export const ContextConsumer = REACT_CONTEXT_TYPE;
65-
export const ContextProvider = REACT_PROVIDER_TYPE;
64+
export const ContextConsumer = REACT_CONSUMER_TYPE;
65+
export const ContextProvider = REACT_CONTEXT_TYPE;
6666
export const Element = REACT_ELEMENT_TYPE;
6767
export const ForwardRef = REACT_FORWARD_REF_TYPE;
6868
export const Fragment = REACT_FRAGMENT_TYPE;
@@ -107,10 +107,10 @@ export function isConcurrentMode(object: any): boolean {
107107
return false;
108108
}
109109
export function isContextConsumer(object: any): boolean {
110-
return typeOf(object) === REACT_CONTEXT_TYPE;
110+
return typeOf(object) === REACT_CONSUMER_TYPE;
111111
}
112112
export function isContextProvider(object: any): boolean {
113-
return typeOf(object) === REACT_PROVIDER_TYPE;
113+
return typeOf(object) === REACT_CONTEXT_TYPE;
114114
}
115115
export function isElement(object: any): boolean {
116116
return (

packages/react-reconciler/src/ReactFiber.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ import {
9494
REACT_DEBUG_TRACING_MODE_TYPE,
9595
REACT_STRICT_MODE_TYPE,
9696
REACT_PROFILER_TYPE,
97-
REACT_PROVIDER_TYPE,
9897
REACT_CONTEXT_TYPE,
98+
REACT_CONSUMER_TYPE,
9999
REACT_SUSPENSE_TYPE,
100100
REACT_SUSPENSE_LIST_TYPE,
101101
REACT_MEMO_TYPE,
@@ -581,10 +581,10 @@ export function createFiberFromTypeAndProps(
581581
default: {
582582
if (typeof type === 'object' && type !== null) {
583583
switch (type.$$typeof) {
584-
case REACT_PROVIDER_TYPE:
584+
case REACT_CONTEXT_TYPE:
585585
fiberTag = ContextProvider;
586586
break getTag;
587-
case REACT_CONTEXT_TYPE:
587+
case REACT_CONSUMER_TYPE:
588588
// This is a consumer
589589
fiberTag = ContextConsumer;
590590
break getTag;

packages/react-reconciler/src/ReactFiberBeginWork.js

+6-33
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
import type {
11-
ReactProviderType,
11+
ReactConsumerType,
1212
ReactContext,
1313
ReactNodeList,
1414
} from 'shared/ReactTypes';
@@ -3532,9 +3532,7 @@ function updateContextProvider(
35323532
workInProgress: Fiber,
35333533
renderLanes: Lanes,
35343534
) {
3535-
const providerType: ReactProviderType<any> = workInProgress.type;
3536-
const context: ReactContext<any> = providerType._context;
3537-
3535+
const context: ReactContext<any> = workInProgress.type;
35383536
const newProps = workInProgress.pendingProps;
35393537
const oldProps = workInProgress.memoizedProps;
35403538

@@ -3591,39 +3589,14 @@ function updateContextProvider(
35913589
return workInProgress.child;
35923590
}
35933591

3594-
let hasWarnedAboutUsingContextAsConsumer = false;
3595-
35963592
function updateContextConsumer(
35973593
current: Fiber | null,
35983594
workInProgress: Fiber,
35993595
renderLanes: Lanes,
36003596
) {
3601-
let context: ReactContext<any> = workInProgress.type;
3602-
// The logic below for Context differs depending on PROD or DEV mode. In
3603-
// DEV mode, we create a separate object for Context.Consumer that acts
3604-
// like a proxy to Context. This proxy object adds unnecessary code in PROD
3605-
// so we use the old behaviour (Context.Consumer references Context) to
3606-
// reduce size and overhead. The separate object references context via
3607-
// a property called "_context", which also gives us the ability to check
3608-
// in DEV mode if this property exists or not and warn if it does not.
3609-
if (__DEV__) {
3610-
if ((context: any)._context === undefined) {
3611-
// This may be because it's a Context (rather than a Consumer).
3612-
// Or it may be because it's older React where they're the same thing.
3613-
// We only want to warn if we're sure it's a new React.
3614-
if (context !== context.Consumer) {
3615-
if (!hasWarnedAboutUsingContextAsConsumer) {
3616-
hasWarnedAboutUsingContextAsConsumer = true;
3617-
console.error(
3618-
'Rendering <Context> directly is not supported and will be removed in ' +
3619-
'a future major release. Did you mean to render <Context.Consumer> instead?',
3620-
);
3621-
}
3622-
}
3623-
} else {
3624-
context = (context: any)._context;
3625-
}
3626-
}
3597+
const consumerType: ReactConsumerType<any> = workInProgress.type;
3598+
const context = consumerType._context;
3599+
36273600
const newProps = workInProgress.pendingProps;
36283601
const render = newProps.children;
36293602

@@ -3869,7 +3842,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
38693842
break;
38703843
case ContextProvider: {
38713844
const newValue = workInProgress.memoizedProps.value;
3872-
const context: ReactContext<any> = workInProgress.type._context;
3845+
const context: ReactContext<any> = workInProgress.type;
38733846
pushProvider(workInProgress, context, newValue);
38743847
break;
38753848
}

packages/react-reconciler/src/ReactFiberClassComponent.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFrom
3232
import getComponentNameFromType from 'shared/getComponentNameFromType';
3333
import assign from 'shared/assign';
3434
import isArray from 'shared/isArray';
35-
import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols';
35+
import {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
3636

3737
import {resolveDefaultProps} from './ReactFiberLazyComponent';
3838
import {
@@ -596,8 +596,7 @@ function constructClassInstance(
596596
// Allow null for conditional declaration
597597
contextType === null ||
598598
(contextType !== undefined &&
599-
contextType.$$typeof === REACT_CONTEXT_TYPE &&
600-
contextType._context === undefined); // Not a <Context.Consumer>
599+
contextType.$$typeof === REACT_CONTEXT_TYPE);
601600

602601
if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {
603602
didWarnAboutInvalidateContextType.add(ctor);
@@ -611,10 +610,7 @@ function constructClassInstance(
611610
'try moving the createContext() call to a separate file.';
612611
} else if (typeof contextType !== 'object') {
613612
addendum = ' However, it is set to a ' + typeof contextType + '.';
614-
} else if (contextType.$$typeof === REACT_PROVIDER_TYPE) {
615-
addendum = ' Did you accidentally pass the Context.Provider instead?';
616-
} else if (contextType._context !== undefined) {
617-
// <Context.Consumer>
613+
} else if (contextType.$$typeof === REACT_CONSUMER_TYPE) {
618614
addendum = ' Did you accidentally pass the Context.Consumer instead?';
619615
} else {
620616
addendum =

0 commit comments

Comments
 (0)