diff --git a/src/isomorphic/classic/element/ReactElement.js b/src/isomorphic/classic/element/ReactElement.js index 024e3b29e36ee..6f885f8fe7a5f 100644 --- a/src/isomorphic/classic/element/ReactElement.js +++ b/src/isomorphic/classic/element/ReactElement.js @@ -243,10 +243,19 @@ ReactElement.cloneElement = function(element, config, children) { key = '' + config.key; } // Remaining properties override existing props + var defaultProps; + if (element.type && element.type.defaultProps) { + defaultProps = element.type.defaultProps; + } for (propName in config) { if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { - props[propName] = config[propName]; + if (config[propName] === undefined && defaultProps !== undefined) { + // Resolve default props + props[propName] = defaultProps[propName]; + } else { + props[propName] = config[propName]; + } } } } diff --git a/src/isomorphic/classic/element/__tests__/ReactElement-test.js b/src/isomorphic/classic/element/__tests__/ReactElement-test.js index 1166ab28eaa75..28ccf663d1cc7 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElement-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElement-test.js @@ -273,6 +273,29 @@ describe('ReactElement', function() { expect(inst2.props.prop).toBe(null); }); + it('should normalize props with default values in cloning', function() { + var Component = React.createClass({ + getDefaultProps: function() { + return {prop: 'testKey'}; + }, + render: function() { + return ; + }, + }); + + var instance = React.createElement(Component); + var clonedInstance = React.cloneElement(instance, {prop: undefined}); + expect(clonedInstance.props.prop).toBe('testKey'); + var clonedInstance2 = React.cloneElement(instance, {prop: null}); + expect(clonedInstance2.props.prop).toBe(null); + + var instance2 = React.createElement(Component, {prop: 'newTestKey'}); + var cloneInstance3 = React.cloneElement(instance2, {prop: undefined}); + expect(cloneInstance3.props.prop).toBe('testKey'); + var cloneInstance4 = React.cloneElement(instance2, {}); + expect(cloneInstance4.props.prop).toBe('newTestKey'); + }); + it('throws when changing a prop (in dev) after element creation', function() { var Outer = React.createClass({ render: function() {