diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
index 14e14fccc5e47..738148ba3b642 100644
--- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js
+++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
@@ -904,4 +904,43 @@ describe('ReactDOMServer', () => {
' in App (at **)',
]);
});
+
+ it('should warn if an invalid contextType is defined', () => {
+ const Context = React.createContext();
+
+ class ComponentA extends React.Component {
+ // It should warn for both Context.Consumer and Context.Provider
+ static contextType = Context.Consumer;
+ render() {
+ return
;
+ }
+ }
+ class ComponentB extends React.Component {
+ static contextType = Context.Provider;
+ render() {
+ return ;
+ }
+ }
+
+ expect(() => {
+ ReactDOMServer.renderToString();
+ }).toWarnDev(
+ 'Warning: ComponentA defines an invalid contextType. ' +
+ 'contextType should point to the Context object returned by React.createContext(). ' +
+ 'Did you accidentally pass the Context.Consumer instead?',
+ {withoutStack: true},
+ );
+
+ // Warnings should be deduped by component type
+ ReactDOMServer.renderToString();
+
+ expect(() => {
+ ReactDOMServer.renderToString();
+ }).toWarnDev(
+ 'Warning: ComponentB defines an invalid contextType. ' +
+ 'contextType should point to the Context object returned by React.createContext(). ' +
+ 'Did you accidentally pass the Context.Provider instead?',
+ {withoutStack: true},
+ );
+ });
});
diff --git a/packages/react-dom/src/server/ReactPartialRendererContext.js b/packages/react-dom/src/server/ReactPartialRendererContext.js
index d7ceaa09758f8..93c857d283715 100644
--- a/packages/react-dom/src/server/ReactPartialRendererContext.js
+++ b/packages/react-dom/src/server/ReactPartialRendererContext.js
@@ -77,7 +77,10 @@ export function processContext(
const contextType = type.contextType;
if (typeof contextType === 'object' && contextType !== null) {
if (__DEV__) {
- if (contextType.$$typeof !== REACT_CONTEXT_TYPE) {
+ const isContextConsumer =
+ contextType.$$typeof === REACT_CONTEXT_TYPE &&
+ contextType._context !== undefined;
+ if (contextType.$$typeof !== REACT_CONTEXT_TYPE || isContextConsumer) {
let name = getComponentName(type) || 'Component';
if (!didWarnAboutInvalidateContextType[name]) {
didWarnAboutInvalidateContextType[name] = true;
@@ -85,8 +88,9 @@ export function processContext(
false,
'%s defines an invalid contextType. ' +
'contextType should point to the Context object returned by React.createContext(). ' +
- 'Did you accidentally pass the Context.Provider instead?',
+ 'Did you accidentally pass the Context.%s instead?',
name,
+ isContextConsumer ? 'Consumer' : 'Provider',
);
}
}
diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js
index 3875371714f38..40c7aca28b9a3 100644
--- a/packages/react-reconciler/src/ReactFiberClassComponent.js
+++ b/packages/react-reconciler/src/ReactFiberClassComponent.js
@@ -515,8 +515,11 @@ function constructClassInstance(
const contextType = ctor.contextType;
if (typeof contextType === 'object' && contextType !== null) {
if (__DEV__) {
+ const isContextConsumer =
+ contextType.$$typeof === REACT_CONTEXT_TYPE &&
+ contextType._context !== undefined;
if (
- contextType.$$typeof !== REACT_CONTEXT_TYPE &&
+ (contextType.$$typeof !== REACT_CONTEXT_TYPE || isContextConsumer) &&
!didWarnAboutInvalidateContextType.has(ctor)
) {
didWarnAboutInvalidateContextType.add(ctor);
@@ -524,8 +527,9 @@ function constructClassInstance(
false,
'%s defines an invalid contextType. ' +
'contextType should point to the Context object returned by React.createContext(). ' +
- 'Did you accidentally pass the Context.Provider instead?',
+ 'Did you accidentally pass the Context.%s instead?',
getComponentName(ctor) || 'Component',
+ isContextConsumer ? 'Consumer' : 'Provider',
);
}
}
diff --git a/packages/react/src/__tests__/ReactContextValidator-test.js b/packages/react/src/__tests__/ReactContextValidator-test.js
index 7ee787e2250d4..b01f008bacb17 100644
--- a/packages/react/src/__tests__/ReactContextValidator-test.js
+++ b/packages/react/src/__tests__/ReactContextValidator-test.js
@@ -541,9 +541,10 @@ describe('ReactContextValidator', () => {
it('should warn if an invalid contextType is defined', () => {
const Context = React.createContext();
-
+ // This tests that both Context.Consumer and Context.Provider
+ // warn about invalid contextType.
class ComponentA extends React.Component {
- static contextType = Context.Provider;
+ static contextType = Context.Consumer;
render() {
return ;
}
@@ -560,7 +561,7 @@ describe('ReactContextValidator', () => {
}).toWarnDev(
'Warning: ComponentA defines an invalid contextType. ' +
'contextType should point to the Context object returned by React.createContext(). ' +
- 'Did you accidentally pass the Context.Provider instead?',
+ 'Did you accidentally pass the Context.Consumer instead?',
{withoutStack: true},
);