Skip to content

Commit

Permalink
Fix Merging propTypes, contextTypes, and childContextTypes
Browse files Browse the repository at this point in the history
This fixes merging of `propTypes`, `contextTypes`, and `childContextTypes` so that we actually merge (instead of only taking the component or last mixin).
  • Loading branch information
yungsters authored and zpao committed Dec 11, 2013
1 parent e92ce38 commit 02de96f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
17 changes: 10 additions & 7 deletions src/core/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,31 @@ var ReactCompositeComponentInterface = {
* @type {object}
* @optional
*/
statics: SpecPolicy.DEFINE_MANY_MERGED,
statics: SpecPolicy.DEFINE_MANY,

/**
* Definition of prop types for this component.
*
* @type {object}
* @optional
*/
propTypes: SpecPolicy.DEFINE_MANY_MERGED,
propTypes: SpecPolicy.DEFINE_MANY,

/**
* Definition of context types for this component.
*
* @type {object}
* @optional
*/
contextTypes: SpecPolicy.DEFINE_MANY_MERGED,
contextTypes: SpecPolicy.DEFINE_MANY,

/**
* Definition of context types this component sets for its children.
*
* @type {object}
* @optional
*/
childContextTypes: SpecPolicy.DEFINE_MANY_MERGED,
childContextTypes: SpecPolicy.DEFINE_MANY,

// ==== Definition methods ====

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand Down
32 changes: 30 additions & 2 deletions src/core/__tests__/ReactCompositeComponentMixin-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,28 @@ describe('ReactCompositeComponent-mixin', function() {
componentPropValidator = mocks.getMockFunction();

var MixinA = {
propTypes: {
propA: function() {}
},
componentDidMount: function() {
this.props.listener('MixinA didMount');
}
};

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');
}
Expand All @@ -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 />;
}
Expand All @@ -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} />;
Expand Down

0 comments on commit 02de96f

Please sign in to comment.