From 90d75ab099be09b25842084cbb3886335e91c5a7 Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 25 Nov 2014 15:43:01 -0800 Subject: [PATCH] Warn if context values differ, related to issue #2112 --- src/core/ReactCompositeComponent.js | 38 +++++++++++----- .../__tests__/ReactCompositeComponent-test.js | 43 ++++++++++++++++++- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index fed6166db5..c3d880ce71 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -597,16 +597,34 @@ var ReactCompositeComponentMixin = assign({}, _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) { var ownerKeys = Object.keys(ownerBasedContext).sort(); var parentKeys = Object.keys(parentBasedContext).sort(); - warning( - ownerKeys.length === parentKeys.length && - ownerKeys.toString() === parentKeys.toString(), - 'owner based context (keys: %s) does not equal parent based' + - ' context (keys: %s) while mounting %s' + - ' (see: http://fb.me/react-context-by-parent)', - Object.keys(ownerBasedContext), - Object.keys(parentBasedContext), - (this._instance.constructor.displayName || 'ReactCompositeComponent') - ); + var displayName = this._instance.constructor.displayName || 'ReactCompositeComponent'; + if (ownerKeys.length !== parentKeys.length || + ownerKeys.toString() !== parentKeys.toString()) { + warning( + ownerKeys.length === parentKeys.length && + ownerKeys.toString() === parentKeys.toString(), + 'owner based context (keys: %s) does not equal parent based ' + + 'context (keys: %s) while mounting %s ' + + '(see: http://fb.me/react-context-by-parent)', + Object.keys(ownerBasedContext), + Object.keys(parentBasedContext), + displayName + ); + } else { + for (key in parentKeys) { + var key = parentKeys[key]; + warning( + ownerBasedContext[key] === parentBasedContext[key], + 'owner-based and parent-based contexts differ ' + + '(values: `%s` vs `%s`) for key (%s) while mounting %s ' + + '(see: http://fb.me/react-context-by-parent)', + ownerBasedContext[key], + parentBasedContext[key], + key, + displayName + ); + } + } }, /** diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index 19aabfd371..b60fd0d94a 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -1009,7 +1009,7 @@ describe('ReactCompositeComponent', function() { reactComponentExpect(grandchildInstance).scalarContextEqual({foo: 'bar', depth: 1}); }); - it('warn if contexts differ', function() { + it('warn if context keys differ', function() { var Component = React.createClass({ contextTypes: { foo: ReactPropTypes.string.isRequired @@ -1033,6 +1033,47 @@ describe('ReactCompositeComponent', function() { }); + it('warn if context values differ', function() { + var Parent = React.createClass({ + childContextTypes: { + foo: ReactPropTypes.string + }, + + getChildContext: function() { + return { + foo: "bar" + }; + }, + + render: function() { + return
{this.props.children}
; + } + }); + var Component = React.createClass({ + contextTypes: { + foo: ReactPropTypes.string.isRequired + }, + + render: function() { + return
; + } + }); + + var component = React.withContext({foo: 'noise'}, function() { + return + }); + + ReactTestUtils.renderIntoDocument({component}); + + expect(console.warn.mock.calls.length).toBe(2); + expect(console.warn.mock.calls[0][0]).toBe( + 'Warning: owner-based and parent-based contexts differ ' + + '(values: `noise` vs `bar`) for key (foo) while mounting Component ' + + '(see: http://fb.me/react-context-by-parent)' + ); + + }); + it('should check context types', function() { var Component = React.createClass({ contextTypes: {