diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 40a94b8bed..fab9ffd78d 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -547,10 +547,14 @@ function mergeObjectsWithNoDuplicateKeys(one, two) { */ function createMergedResultFunction(one, two) { return function mergedResult() { - return mergeObjectsWithNoDuplicateKeys( - one.apply(this, arguments), - two.apply(this, arguments) - ); + var a = one.apply(this, arguments); + var b = two.apply(this, arguments); + if (a == null) { + return b; + } else if (b == null) { + return a; + } + return mergeObjectsWithNoDuplicateKeys(a, b); }; } diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index ed75168de4..d7fa8feb80 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -477,30 +477,6 @@ describe('ReactCompositeComponent', function() { ); }); - it('should throw with bad getInitialState() return values', function() { - var Mixin = { - getInitialState: function() { - return null; - } - }; - var Component = React.createClass({ - mixins: [Mixin], - getInitialState: function() { - return {x: true}; - }, - render: function() { - return ; - } - }); - var instance = ; - expect(function() { - ReactTestUtils.renderIntoDocument(instance); - }).toThrow( - 'Invariant Violation: mergeObjectsWithNoDuplicateKeys(): ' + - 'Cannot merge non-objects' - ); - }); - it('should work with object getInitialState() return values', function() { var Component = React.createClass({ getInitialState: function() { @@ -546,7 +522,77 @@ describe('ReactCompositeComponent', function() { return ; } }); - expect(() => ).not.toThrow(); + expect( + () => ReactTestUtils.renderIntoDocument() + ).not.toThrow(); + }); + + it('should work with a null getInitialState return value and a mixin', () => { + var Component; + var instance; + + var Mixin = { + getInitialState: function() { + return {foo: 'bar'}; + } + }; + Component = React.createClass({ + mixins: [Mixin], + getInitialState: function() { + return null; + }, + render: function() { + return ; + } + }); + expect( + () => ReactTestUtils.renderIntoDocument() + ).not.toThrow(); + + instance = ; + ReactTestUtils.renderIntoDocument(instance); + expect(instance.state).toEqual({foo: 'bar'}); + + // Also the other way round should work + var Mixin2 = { + getInitialState: function() { + return null; + } + }; + Component = React.createClass({ + mixins: [Mixin2], + getInitialState: function() { + return {foo: 'bar'}; + }, + render: function() { + return ; + } + }); + expect( + () => ReactTestUtils.renderIntoDocument() + ).not.toThrow(); + + instance = ; + ReactTestUtils.renderIntoDocument(instance); + expect(instance.state).toEqual({foo: 'bar'}); + + // Multiple mixins should be fine too + Component = React.createClass({ + mixins: [Mixin, Mixin2], + getInitialState: function() { + return {x: true}; + }, + render: function() { + return ; + } + }); + expect( + () => ReactTestUtils.renderIntoDocument() + ).not.toThrow(); + + instance = ; + ReactTestUtils.renderIntoDocument(instance); + expect(instance.state).toEqual({foo: 'bar', x: true}); }); it('should work with object getInitialState() return values', function() {