@samitouri / QOS-React-2 / commits / 0906d282ec

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 });