From 0906d282ec63e9e99be4edcf0f715cd344f2f9ac Mon Sep 17 00:00:00 2001 From: Cheng Lou Date: Tue, 14 Jan 2014 21:11:25 -0800 Subject: [PATCH] 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 --- src/core/ReactCompositeComponent.js | 36 ++++++++++++------- .../__tests__/ReactCompositeComponent-test.js | 36 +++++++++++++++++++ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index dc01652dc4..7edda3b642 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -430,6 +430,17 @@ function validateLifeCycleOnReplaceState(instance) { * specification keys when building `ReactCompositeComponent` classses. */ function mixSpecIntoComponent(ConvenienceConstructor, spec) { + invariant( + !isValidClass(spec), + 'ReactCompositeComponent: You\'re attempting to ' + + 'use a component class as a mixin. Instead, just use a regular object.' + ); + invariant( + !ReactComponent.isValidComponent(spec), + 'ReactCompositeComponent: You\'re attempting to ' + + 'use a component as a mixin. Instead, just use a regular object.' + ); + var Constructor = ConvenienceConstructor.componentConstructor; var proto = Constructor.prototype; for (var name in spec) { @@ -1211,6 +1222,18 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin); mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin); mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin); +/** + * Checks if a value is a valid component constructor. + * + * @param {*} + * @return {boolean} + * @public + */ +function isValidClass(componentClass) { + return componentClass instanceof Function && + 'componentConstructor' in componentClass && + componentClass.componentConstructor instanceof Function; +} /** * Module for creating composite components. * @@ -1274,18 +1297,7 @@ var ReactCompositeComponent = { return ConvenienceConstructor; }, - /** - * Checks if a value is a valid component constructor. - * - * @param {*} - * @return {boolean} - * @public - */ - isValidClass: function(componentClass) { - return componentClass instanceof Function && - 'componentConstructor' in componentClass && - componentClass.componentConstructor instanceof Function; - } + isValidClass: isValidClass }; module.exports = ReactCompositeComponent; diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index d7fa8feb80..a0695f1eed 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -1068,4 +1068,40 @@ describe('ReactCompositeComponent', function() { 'may be due to a mixin.' ); }); + + it("should throw if the mixin is a React component", function() { + expect(function() { + React.createClass({ + mixins: [
], + + render: function() { + return ; + } + }); + }).toThrow( + 'Invariant Violation: ReactCompositeComponent: You\'re attempting to ' + + 'use a component as a mixin. Instead, just use a regular object.' + ); + }); + + it("should throw if the mixin is a React component class", function() { + expect(function() { + var Component = React.createClass({ + render: function() { + return ; + } + }); + + React.createClass({ + mixins: [Component], + + render: function() { + return ; + } + }); + }).toThrow( + 'Invariant Violation: ReactCompositeComponent: You\'re attempting to ' + + 'use a component class as a mixin. Instead, just use a regular object.' + ); + }); });