Dedupe missing getChildContext warning by component name
Brian Vaughn committed
Jan 10, 2017 at 14:00 UTC
4f08884b5d132ed7275261769e403ce44517dcc7
4 files changed
+59
-10
scripts/fiber/tests-passing.txt
+1
@@ -159,6 +159,7 @@ src/isomorphic/classic/__tests__/ReactContextValidator-test.js
159
* should check child context types
160
* should warn (but not error) if getChildContext method is missing
161
* should pass parent context if getChildContext method is missing
162
+* should only warn about missing getChildContext once per component type
163
164
src/isomorphic/classic/class/__tests__/ReactBind-test.js
165
* Holds reference to instance
src/isomorphic/classic/__tests__/ReactContextValidator-test.js
+34
@@ -356,4 +356,38 @@ describe('ReactContextValidator', () => {
356
expect(childContext.foo).toBe('FOO');
357
});
358
359
+ it('should only warn about missing getChildContext once per component type', () => {
360
+ spyOn(console, 'error');
361
+
362
+ class ComponentA extends React.Component {
363
+ static childContextTypes = {
364
+ foo: React.PropTypes.string.isRequired,
365
+ };
366
+ render() {
367
+ return <div />;
368
+ }
369
+ }
370
+ class ComponentB extends React.Component {
371
+ static childContextTypes = {
372
+ foo: React.PropTypes.string.isRequired,
373
+ };
374
+ render() {
375
+ return <div />;
376
+ }
377
+ }
378
+
379
+ ReactTestUtils.renderIntoDocument(<ComponentA/>);
380
+ expectDev(console.error.calls.count()).toBe(1);
381
+ expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
382
+ 'Warning: getChildContext() is not defined for ComponentA'
383
+ );
384
+ ReactTestUtils.renderIntoDocument(<ComponentA/>);
385
+ expectDev(console.error.calls.count()).toBe(1);
386
+ ReactTestUtils.renderIntoDocument(<ComponentB/>);
387
+ expectDev(console.error.calls.count()).toBe(2);
388
+ expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
389
+ 'Warning: getChildContext() is not defined for ComponentB'
390
+ );
391
+ });
392
+
393
});
src/renderers/shared/fiber/ReactFiberContext.js
+13
-5
@@ -34,6 +34,7 @@ const {
34
35
if (__DEV__) {
36
var checkReactTypeSpec = require('checkReactTypeSpec');
37
+ var warningAboutMissingGetChildContext = {};
38
}
39
40
// A cursor to the current merged context object on the stack.
@@ -146,11 +147,18 @@ function processChildContext(fiber : Fiber, parentContext : Object, isReconcilin
147
// TODO (bvaughn) Replace this behavior with an invariant() in the future.
148
// It has only been added in Fiber to match the (unintentional) behavior in Stack.
149
if (typeof instance.getChildContext !== 'function') {
149
- warning(
150
- false,
151
- 'getChildContext() is not defined for %s',
152
- getComponentName(fiber),
153
- );
150
+ if (__DEV__) {
151
+ const componentName = getComponentName(fiber);
152
+
153
+ if (!warningAboutMissingGetChildContext[componentName]) {
154
+ warningAboutMissingGetChildContext[componentName] = true;
155
+ warning(
156
+ false,
157
+ 'getChildContext() is not defined for %s',
158
+ componentName,
159
+ );
160
+ }
161
+ }
162
return parentContext;
163
}
164
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
+11
-5
@@ -24,6 +24,7 @@ var ReactReconciler = require('ReactReconciler');
24
25
if (__DEV__) {
26
var checkReactTypeSpec = require('checkReactTypeSpec');
27
+ var warningAboutMissingGetChildContext = {};
28
}
29
30
var emptyObject = require('emptyObject');
@@ -700,11 +701,16 @@ var ReactCompositeComponent = {
701
return Object.assign({}, currentContext, childContext);
702
} else {
703
if (__DEV__) {
703
- warning(
704
- !Component.childContextTypes,
705
- 'getChildContext() is not defined for %s',
706
- this.getName(),
707
- );
704
+ const componentName = this.getName();
705
+
706
+ if (!warningAboutMissingGetChildContext[componentName]) {
707
+ warningAboutMissingGetChildContext[componentName] = true;
708
+ warning(
709
+ !Component.childContextTypes,
710
+ 'getChildContext() is not defined for %s',
711
+ componentName,
712
+ );
713
+ }
714
}
715
}
716
return currentContext;