From 7a2e35b93b20f702c274dcfcddf4a184e82a7cc3 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Thu, 12 Jan 2017 17:11:53 -0800 Subject: [PATCH] Improved error message wording for missing getChildContext() method --- .../__tests__/ReactContextValidator-test.js | 36 ++++++++++--------- .../shared/fiber/ReactFiberContext.js | 11 +++--- .../__tests__/ReactStatelessComponent-test.js | 6 ++-- .../reconciler/ReactCompositeComponent.js | 5 ++- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/isomorphic/classic/__tests__/ReactContextValidator-test.js b/src/isomorphic/classic/__tests__/ReactContextValidator-test.js index 883764e067..08582a200d 100644 --- a/src/isomorphic/classic/__tests__/ReactContextValidator-test.js +++ b/src/isomorphic/classic/__tests__/ReactContextValidator-test.js @@ -314,7 +314,9 @@ describe('ReactContextValidator', () => { ReactTestUtils.renderIntoDocument(); expectDev(console.error.calls.count()).toBe(1); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( - 'Warning: getChildContext() is not defined for ComponentA' + 'Warning: ComponentA.childContextTypes is specified but there is no ' + + 'getChildContext() method on the instance. You can either define ' + + 'getChildContext() on ComponentA or remove childContextTypes from it.' ); // Warnings should be deduped by component type @@ -323,7 +325,9 @@ describe('ReactContextValidator', () => { ReactTestUtils.renderIntoDocument(); expectDev(console.error.calls.count()).toBe(2); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe( - 'Warning: getChildContext() is not defined for ComponentB' + 'Warning: ComponentB.childContextTypes is specified but there is no ' + + 'getChildContext() method on the instance. You can either define ' + + 'getChildContext() on ComponentB or remove childContextTypes from it.' ); }); @@ -332,28 +336,28 @@ describe('ReactContextValidator', () => { it('should pass parent context if getChildContext method is missing', () => { spyOn(console, 'error'); - var ParentContextProvider = React.createClass({ - childContextTypes: { + class ParentContextProvider extends React.Component { + static childContextTypes = { foo: React.PropTypes.number, - }, - getChildContext: function() { + }; + getChildContext() { return { foo: 'FOO', }; - }, - render: function() { + } + render() { return ; - }, - }); + } + } - var MiddleMissingContext = React.createClass({ - childContextTypes: { + class MiddleMissingContext extends React.Component { + static childContextTypes = { bar: React.PropTypes.string.isRequired, - }, - render: function() { + }; + render() { return ; - }, - }); + } + } var childContext; var ChildContextConsumer = React.createClass({ diff --git a/src/renderers/shared/fiber/ReactFiberContext.js b/src/renderers/shared/fiber/ReactFiberContext.js index b3a4f61e53..322affe797 100644 --- a/src/renderers/shared/fiber/ReactFiberContext.js +++ b/src/renderers/shared/fiber/ReactFiberContext.js @@ -34,7 +34,7 @@ const { if (__DEV__) { var checkReactTypeSpec = require('checkReactTypeSpec'); - var warningAboutMissingGetChildContext = {}; + var warnedAboutMissingGetChildContext = {}; } // A cursor to the current merged context object on the stack. @@ -150,11 +150,14 @@ function processChildContext(fiber : Fiber, parentContext : Object, isReconcilin if (__DEV__) { const componentName = getComponentName(fiber); - if (!warningAboutMissingGetChildContext[componentName]) { - warningAboutMissingGetChildContext[componentName] = true; + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; warning( false, - 'getChildContext() is not defined for %s', + '%s.childContextTypes is specified but there is no getChildContext() method ' + + 'on the instance. You can either define getChildContext() on %s or remove ' + + 'childContextTypes from it.', + componentName, componentName, ); } diff --git a/src/renderers/shared/shared/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/shared/__tests__/ReactStatelessComponent-test.js index 94291c816d..b31706c66b 100644 --- a/src/renderers/shared/shared/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/shared/__tests__/ReactStatelessComponent-test.js @@ -124,8 +124,10 @@ describe('ReactStatelessComponent', () => { 'be defined on a functional component.' ); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe( - 'Warning: getChildContext() is not defined for ' + - 'StatelessComponentWithChildContext' + 'Warning: StatelessComponentWithChildContext.childContextTypes is specified ' + + 'but there is no getChildContext() method on the instance. You can either ' + + 'define getChildContext() on StatelessComponentWithChildContext or remove ' + + 'childContextTypes from it.' ); }); diff --git a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js index d93135e51a..e7aa14ef93 100644 --- a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js @@ -707,7 +707,10 @@ var ReactCompositeComponent = { warningAboutMissingGetChildContext[componentName] = true; warning( !Component.childContextTypes, - 'getChildContext() is not defined for %s', + '%s.childContextTypes is specified but there is no getChildContext() method ' + + 'on the instance. You can either define getChildContext() on %s or remove ' + + 'childContextTypes from it.', + componentName, componentName, ); }