throw when using component/component class as mixin
throw invariant error to help people new to mixins, so that they don't get misled into trying to mixin components into another component
Cheng Lou committed
Jan 14, 2014 at 21:11 UTC
0906d282ec63e9e99be4edcf0f715cd344f2f9ac
2 files changed
+60
-12
src/core/ReactCompositeComponent.js
+24
-12
@@ -430,6 +430,17 @@ function validateLifeCycleOnReplaceState(instance) {
430
* specification keys when building `ReactCompositeComponent` classses.
431
*/
432
function mixSpecIntoComponent(ConvenienceConstructor, spec) {
433
+ invariant(
434
+ !isValidClass(spec),
435
+ 'ReactCompositeComponent: You\'re attempting to ' +
436
+ 'use a component class as a mixin. Instead, just use a regular object.'
437
+ );
438
+ invariant(
439
+ !ReactComponent.isValidComponent(spec),
440
+ 'ReactCompositeComponent: You\'re attempting to ' +
441
+ 'use a component as a mixin. Instead, just use a regular object.'
442
+ );
443
+
444
var Constructor = ConvenienceConstructor.componentConstructor;
445
var proto = Constructor.prototype;
446
for (var name in spec) {
@@ -1211,6 +1222,18 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
1222
mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
1223
mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
1224
1225
+/**
1226
+ * Checks if a value is a valid component constructor.
1227
+ *
1228
+ * @param {*}
1229
+ * @return {boolean}
1230
+ * @public
1231
+ */
1232
+function isValidClass(componentClass) {
1233
+ return componentClass instanceof Function &&
1234
+ 'componentConstructor' in componentClass &&
1235
+ componentClass.componentConstructor instanceof Function;
1236
+}
1237
/**
1238
* Module for creating composite components.
1239
*
@@ -1274,18 +1297,7 @@ var ReactCompositeComponent = {
1297
return ConvenienceConstructor;
1298
},
1299
1277
- /**
1278
- * Checks if a value is a valid component constructor.
1279
- *
1280
- * @param {*}
1281
- * @return {boolean}
1282
- * @public
1283
- */
1284
- isValidClass: function(componentClass) {
1285
- return componentClass instanceof Function &&
1286
- 'componentConstructor' in componentClass &&
1287
- componentClass.componentConstructor instanceof Function;
1288
- }
1300
+ isValidClass: isValidClass
1301
};
1302
1303
module.exports = ReactCompositeComponent;
src/core/__tests__/ReactCompositeComponent-test.js
+36
@@ -1068,4 +1068,40 @@ describe('ReactCompositeComponent', function() {
1068
'may be due to a mixin.'
1069
);
1070
});
1071
+
1072
+ it("should throw if the mixin is a React component", function() {
1073
+ expect(function() {
1074
+ React.createClass({
1075
+ mixins: [<div />],
1076
+
1077
+ render: function() {
1078
+ return <span />;
1079
+ }
1080
+ });
1081
+ }).toThrow(
1082
+ 'Invariant Violation: ReactCompositeComponent: You\'re attempting to ' +
1083
+ 'use a component as a mixin. Instead, just use a regular object.'
1084
+ );
1085
+ });
1086
+
1087
+ it("should throw if the mixin is a React component class", function() {
1088
+ expect(function() {
1089
+ var Component = React.createClass({
1090
+ render: function() {
1091
+ return <span />;
1092
+ }
1093
+ });
1094
+
1095
+ React.createClass({
1096
+ mixins: [Component],
1097
+
1098
+ render: function() {
1099
+ return <span />;
1100
+ }
1101
+ });
1102
+ }).toThrow(
1103
+ 'Invariant Violation: ReactCompositeComponent: You\'re attempting to ' +
1104
+ 'use a component class as a mixin. Instead, just use a regular object.'
1105
+ );
1106
+ });
1107
});