Warn for Context.Consumer with contextType (#14831)
Brandon Dail committed
Mar 18, 2019 at 12:27 UTC
df7b87d25e74fbbaf19b822096d0651aa3ad6a9f
4 files changed
+55
-7
packages/react-dom/src/__tests__/ReactServerRendering-test.js
+39
@@ -904,4 +904,43 @@ describe('ReactDOMServer', () => {
904
' in App (at **)',
905
]);
906
});
907
+
908
+ it('should warn if an invalid contextType is defined', () => {
909
+ const Context = React.createContext();
910
+
911
+ class ComponentA extends React.Component {
912
+ // It should warn for both Context.Consumer and Context.Provider
913
+ static contextType = Context.Consumer;
914
+ render() {
915
+ return <div />;
916
+ }
917
+ }
918
+ class ComponentB extends React.Component {
919
+ static contextType = Context.Provider;
920
+ render() {
921
+ return <div />;
922
+ }
923
+ }
924
+
925
+ expect(() => {
926
+ ReactDOMServer.renderToString(<ComponentA />);
927
+ }).toWarnDev(
928
+ 'Warning: ComponentA defines an invalid contextType. ' +
929
+ 'contextType should point to the Context object returned by React.createContext(). ' +
930
+ 'Did you accidentally pass the Context.Consumer instead?',
931
+ {withoutStack: true},
932
+ );
933
+
934
+ // Warnings should be deduped by component type
935
+ ReactDOMServer.renderToString(<ComponentA />);
936
+
937
+ expect(() => {
938
+ ReactDOMServer.renderToString(<ComponentB />);
939
+ }).toWarnDev(
940
+ 'Warning: ComponentB defines an invalid contextType. ' +
941
+ 'contextType should point to the Context object returned by React.createContext(). ' +
942
+ 'Did you accidentally pass the Context.Provider instead?',
943
+ {withoutStack: true},
944
+ );
945
+ });
946
});
packages/react-dom/src/server/ReactPartialRendererContext.js
+6
-2
@@ -77,7 +77,10 @@ export function processContext(
77
const contextType = type.contextType;
78
if (typeof contextType === 'object' && contextType !== null) {
79
if (__DEV__) {
80
- if (contextType.$$typeof !== REACT_CONTEXT_TYPE) {
80
+ const isContextConsumer =
81
+ contextType.$$typeof === REACT_CONTEXT_TYPE &&
82
+ contextType._context !== undefined;
83
+ if (contextType.$$typeof !== REACT_CONTEXT_TYPE || isContextConsumer) {
84
let name = getComponentName(type) || 'Component';
85
if (!didWarnAboutInvalidateContextType[name]) {
86
didWarnAboutInvalidateContextType[name] = true;
@@ -85,8 +88,9 @@ export function processContext(
88
false,
89
'%s defines an invalid contextType. ' +
90
'contextType should point to the Context object returned by React.createContext(). ' +
88
- 'Did you accidentally pass the Context.Provider instead?',
91
+ 'Did you accidentally pass the Context.%s instead?',
92
name,
93
+ isContextConsumer ? 'Consumer' : 'Provider',
94
);
95
}
96
}
packages/react-reconciler/src/ReactFiberClassComponent.js
+6
-2
@@ -515,8 +515,11 @@ function constructClassInstance(
515
const contextType = ctor.contextType;
516
if (typeof contextType === 'object' && contextType !== null) {
517
if (__DEV__) {
518
+ const isContextConsumer =
519
+ contextType.$$typeof === REACT_CONTEXT_TYPE &&
520
+ contextType._context !== undefined;
521
if (
519
- contextType.$$typeof !== REACT_CONTEXT_TYPE &&
522
+ (contextType.$$typeof !== REACT_CONTEXT_TYPE || isContextConsumer) &&
523
!didWarnAboutInvalidateContextType.has(ctor)
524
) {
525
didWarnAboutInvalidateContextType.add(ctor);
@@ -524,8 +527,9 @@ function constructClassInstance(
527
false,
528
'%s defines an invalid contextType. ' +
529
'contextType should point to the Context object returned by React.createContext(). ' +
527
- 'Did you accidentally pass the Context.Provider instead?',
530
+ 'Did you accidentally pass the Context.%s instead?',
531
getComponentName(ctor) || 'Component',
532
+ isContextConsumer ? 'Consumer' : 'Provider',
533
);
534
}
535
}
packages/react/src/__tests__/ReactContextValidator-test.js
+4
-3
@@ -541,9 +541,10 @@ describe('ReactContextValidator', () => {
541
542
it('should warn if an invalid contextType is defined', () => {
543
const Context = React.createContext();
544
-
544
+ // This tests that both Context.Consumer and Context.Provider
545
+ // warn about invalid contextType.
546
class ComponentA extends React.Component {
546
- static contextType = Context.Provider;
547
+ static contextType = Context.Consumer;
548
render() {
549
return <div />;
550
}
@@ -560,7 +561,7 @@ describe('ReactContextValidator', () => {
561
}).toWarnDev(
562
'Warning: ComponentA defines an invalid contextType. ' +
563
'contextType should point to the Context object returned by React.createContext(). ' +
563
- 'Did you accidentally pass the Context.Provider instead?',
564
+ 'Did you accidentally pass the Context.Consumer instead?',
565
{withoutStack: true},
566
);
567