@samitouri / QOS-React / commits / df7b87d25e

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