Fix Merging propTypes, contextTypes, and childContextTypes

This fixes merging of `propTypes`, `contextTypes`, and `childContextTypes` so that we actually merge (instead of only taking the component or last mixin).
This commit is contained in:
Tim Yung
2013-12-11 13:45:55 -08:00
committed by Paul O’Shannessy
parent e92ce38cf1
commit 02de96f012
2 changed files with 40 additions and 9 deletions
+10 -7
View File
@@ -100,7 +100,7 @@ var ReactCompositeComponentInterface = {
* @type {object}
* @optional
*/
statics: SpecPolicy.DEFINE_MANY_MERGED,
statics: SpecPolicy.DEFINE_MANY,
/**
* Definition of prop types for this component.
@@ -108,7 +108,7 @@ var ReactCompositeComponentInterface = {
* @type {object}
* @optional
*/
propTypes: SpecPolicy.DEFINE_MANY_MERGED,
propTypes: SpecPolicy.DEFINE_MANY,
/**
* Definition of context types for this component.
@@ -116,7 +116,7 @@ var ReactCompositeComponentInterface = {
* @type {object}
* @optional
*/
contextTypes: SpecPolicy.DEFINE_MANY_MERGED,
contextTypes: SpecPolicy.DEFINE_MANY,
/**
* Definition of context types this component sets for its children.
@@ -124,7 +124,7 @@ var ReactCompositeComponentInterface = {
* @type {object}
* @optional
*/
childContextTypes: SpecPolicy.DEFINE_MANY_MERGED,
childContextTypes: SpecPolicy.DEFINE_MANY,
// ==== Definition methods ====
@@ -337,7 +337,10 @@ var RESERVED_SPEC_KEYS = {
childContextTypes,
ReactPropTypeLocations.childContext
);
Constructor.childContextTypes = childContextTypes;
Constructor.childContextTypes = merge(
Constructor.childContextTypes,
childContextTypes
);
},
contextTypes: function(ConvenienceConstructor, contextTypes) {
var Constructor = ConvenienceConstructor.componentConstructor;
@@ -346,7 +349,7 @@ var RESERVED_SPEC_KEYS = {
contextTypes,
ReactPropTypeLocations.context
);
Constructor.contextTypes = contextTypes;
Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
},
propTypes: function(ConvenienceConstructor, propTypes) {
var Constructor = ConvenienceConstructor.componentConstructor;
@@ -355,7 +358,7 @@ var RESERVED_SPEC_KEYS = {
propTypes,
ReactPropTypeLocations.prop
);
Constructor.propTypes = propTypes;
Constructor.propTypes = merge(Constructor.propTypes, propTypes);
},
statics: function(ConvenienceConstructor, statics) {
mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
@@ -40,6 +40,9 @@ describe('ReactCompositeComponent-mixin', function() {
componentPropValidator = mocks.getMockFunction();
var MixinA = {
propTypes: {
propA: function() {}
},
componentDidMount: function() {
this.props.listener('MixinA didMount');
}
@@ -47,12 +50,18 @@ describe('ReactCompositeComponent-mixin', function() {
var MixinB = {
mixins: [MixinA],
propTypes: {
propB: function() {}
},
componentDidMount: function() {
this.props.listener('MixinB didMount');
}
};
var MixinC = {
statics: {
staticC: function() {}
},
componentDidMount: function() {
this.props.listener('MixinC didMount');
}
@@ -66,11 +75,15 @@ describe('ReactCompositeComponent-mixin', function() {
TestComponent = React.createClass({
mixins: [MixinB, MixinC, MixinD],
statics: {
staticComponent: function() {}
},
propTypes: {
propComponent: function() {}
},
componentDidMount: function() {
this.props.listener('Component didMount');
},
render: function() {
return <div />;
}
@@ -87,6 +100,21 @@ describe('ReactCompositeComponent-mixin', function() {
});
});
it('should support merging propTypes and statics', function() {
var listener = mocks.getMockFunction();
var instance = <TestComponent listener={listener} />;
ReactTestUtils.renderIntoDocument(instance);
var instancePropTypes = instance.constructor.propTypes;
expect('propA' in instancePropTypes).toBe(true);
expect('propB' in instancePropTypes).toBe(true);
expect('propComponent' in instancePropTypes).toBe(true);
expect('staticC' in TestComponent).toBe(true);
expect('staticComponent' in TestComponent).toBe(true);
});
it('should support chaining delegate functions', function() {
var listener = mocks.getMockFunction();
var instance = <TestComponent listener={listener} />;