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).
Tim Yung committed
Dec 11, 2013 at 13:40 UTC
02de96f012cc535659eb26b79b9827d6e1f7eb7d
2 files changed
+40
-9
src/core/ReactCompositeComponent.js
+10
-7
@@ -100,7 +100,7 @@ var ReactCompositeComponentInterface = {
100
* @type {object}
101
* @optional
102
*/
103
- statics: SpecPolicy.DEFINE_MANY_MERGED,
103
+ statics: SpecPolicy.DEFINE_MANY,
104
105
/**
106
* Definition of prop types for this component.
@@ -108,7 +108,7 @@ var ReactCompositeComponentInterface = {
108
* @type {object}
109
* @optional
110
*/
111
- propTypes: SpecPolicy.DEFINE_MANY_MERGED,
111
+ propTypes: SpecPolicy.DEFINE_MANY,
112
113
/**
114
* Definition of context types for this component.
@@ -116,7 +116,7 @@ var ReactCompositeComponentInterface = {
116
* @type {object}
117
* @optional
118
*/
119
- contextTypes: SpecPolicy.DEFINE_MANY_MERGED,
119
+ contextTypes: SpecPolicy.DEFINE_MANY,
120
121
/**
122
* Definition of context types this component sets for its children.
@@ -124,7 +124,7 @@ var ReactCompositeComponentInterface = {
124
* @type {object}
125
* @optional
126
*/
127
- childContextTypes: SpecPolicy.DEFINE_MANY_MERGED,
127
+ childContextTypes: SpecPolicy.DEFINE_MANY,
128
129
// ==== Definition methods ====
130
@@ -337,7 +337,10 @@ var RESERVED_SPEC_KEYS = {
337
childContextTypes,
338
ReactPropTypeLocations.childContext
339
);
340
- Constructor.childContextTypes = childContextTypes;
340
+ Constructor.childContextTypes = merge(
341
+ Constructor.childContextTypes,
342
+ childContextTypes
343
+ );
344
},
345
contextTypes: function(ConvenienceConstructor, contextTypes) {
346
var Constructor = ConvenienceConstructor.componentConstructor;
@@ -346,7 +349,7 @@ var RESERVED_SPEC_KEYS = {
349
contextTypes,
350
ReactPropTypeLocations.context
351
);
349
- Constructor.contextTypes = contextTypes;
352
+ Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
353
},
354
propTypes: function(ConvenienceConstructor, propTypes) {
355
var Constructor = ConvenienceConstructor.componentConstructor;
@@ -355,7 +358,7 @@ var RESERVED_SPEC_KEYS = {
358
propTypes,
359
ReactPropTypeLocations.prop
360
);
358
- Constructor.propTypes = propTypes;
361
+ Constructor.propTypes = merge(Constructor.propTypes, propTypes);
362
},
363
statics: function(ConvenienceConstructor, statics) {
364
mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
src/core/__tests__/ReactCompositeComponentMixin-test.js
+30
-2
@@ -40,6 +40,9 @@ describe('ReactCompositeComponent-mixin', function() {
40
componentPropValidator = mocks.getMockFunction();
41
42
var MixinA = {
43
+ propTypes: {
44
+ propA: function() {}
45
+ },
46
componentDidMount: function() {
47
this.props.listener('MixinA didMount');
48
}
@@ -47,12 +50,18 @@ describe('ReactCompositeComponent-mixin', function() {
50
51
var MixinB = {
52
mixins: [MixinA],
53
+ propTypes: {
54
+ propB: function() {}
55
+ },
56
componentDidMount: function() {
57
this.props.listener('MixinB didMount');
58
}
59
};
60
61
var MixinC = {
62
+ statics: {
63
+ staticC: function() {}
64
+ },
65
componentDidMount: function() {
66
this.props.listener('MixinC didMount');
67
}
@@ -66,11 +75,15 @@ describe('ReactCompositeComponent-mixin', function() {
75
76
TestComponent = React.createClass({
77
mixins: [MixinB, MixinC, MixinD],
69
-
78
+ statics: {
79
+ staticComponent: function() {}
80
+ },
81
+ propTypes: {
82
+ propComponent: function() {}
83
+ },
84
componentDidMount: function() {
85
this.props.listener('Component didMount');
86
},
73
-
87
render: function() {
88
return <div />;
89
}
@@ -87,6 +100,21 @@ describe('ReactCompositeComponent-mixin', function() {
100
});
101
});
102
103
+ it('should support merging propTypes and statics', function() {
104
+ var listener = mocks.getMockFunction();
105
+ var instance = <TestComponent listener={listener} />;
106
+ ReactTestUtils.renderIntoDocument(instance);
107
+
108
+ var instancePropTypes = instance.constructor.propTypes;
109
+
110
+ expect('propA' in instancePropTypes).toBe(true);
111
+ expect('propB' in instancePropTypes).toBe(true);
112
+ expect('propComponent' in instancePropTypes).toBe(true);
113
+
114
+ expect('staticC' in TestComponent).toBe(true);
115
+ expect('staticComponent' in TestComponent).toBe(true);
116
+ });
117
+
118
it('should support chaining delegate functions', function() {
119
var listener = mocks.getMockFunction();
120
var instance = <TestComponent listener={listener} />;