Skip to content

Commit

Permalink
Warn for Context.Consumer with contextType (#14831)
Browse files Browse the repository at this point in the history
  • Loading branch information
aweary authored and gaearon committed Mar 18, 2019
1 parent 2b93d68 commit df7b87d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 7 deletions.
39 changes: 39 additions & 0 deletions packages/react-dom/src/__tests__/ReactServerRendering-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <div />;
}
}
class ComponentB extends React.Component {
static contextType = Context.Provider;
render() {
return <div />;
}
}

expect(() => {
ReactDOMServer.renderToString(<ComponentA />);
}).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(<ComponentA />);

expect(() => {
ReactDOMServer.renderToString(<ComponentB />);
}).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},
);
});
});
8 changes: 6 additions & 2 deletions packages/react-dom/src/server/ReactPartialRendererContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,20 @@ 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;
warningWithoutStack(
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',
);
}
}
Expand Down
8 changes: 6 additions & 2 deletions packages/react-reconciler/src/ReactFiberClassComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,17 +515,21 @@ 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);
warningWithoutStack(
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',
);
}
}
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/__tests__/ReactContextValidator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <div />;
}
Expand All @@ -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},
);

Expand Down

0 comments on commit df7b87d

Please sign in to comment.