diff --git a/src/isomorphic/React.js b/src/isomorphic/React.js
index 5e57605f1c..a37649a319 100644
--- a/src/isomorphic/React.js
+++ b/src/isomorphic/React.js
@@ -13,7 +13,6 @@
var ReactBaseClasses = require('ReactBaseClasses');
var ReactChildren = require('ReactChildren');
-var ReactClass = require('ReactClass');
var ReactDOMFactories = require('ReactDOMFactories');
var ReactElement = require('ReactElement');
var ReactPropTypes = require('ReactPropTypes');
@@ -75,7 +74,6 @@ var React = {
// Classic
PropTypes: ReactPropTypes,
- createClass: ReactClass.createClass,
createFactory: createFactory,
createMixin: createMixin,
diff --git a/src/isomorphic/classic/class/ReactClass.js b/src/isomorphic/classic/class/ReactClass.js
deleted file mode 100644
index fb1c07ec08..0000000000
--- a/src/isomorphic/classic/class/ReactClass.js
+++ /dev/null
@@ -1,833 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule ReactClass
- */
-
-'use strict';
-
-var ReactBaseClasses = require('ReactBaseClasses');
-var ReactElement = require('ReactElement');
-var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');
-
-var emptyObject = require('fbjs/lib/emptyObject');
-var invariant = require('fbjs/lib/invariant');
-var warning = require('fbjs/lib/warning');
-
-var ReactComponent = ReactBaseClasses.Component;
-
-var MIXINS_KEY = 'mixins';
-
-// Helper function to allow the creation of anonymous functions which do not
-// have .name set to the name of the variable being assigned to.
-function identity(fn) {
- return fn;
-}
-
-/**
- * Policies that describe methods in `ReactClassInterface`.
- */
-type SpecPolicy =
- /**
- * These methods may be defined only once by the class specification or mixin.
- */
- | 'DEFINE_ONCE' /**
- * These methods may be defined by both the class specification and mixins.
- * Subsequent definitions will be chained. These methods must return void.
- */
- | 'DEFINE_MANY' /**
- * These methods are overriding the base class.
- */
- | 'OVERRIDE_BASE' /**
- * These methods are similar to DEFINE_MANY, except we assume they return
- * objects. We try to merge the keys of the return values of all the mixed in
- * functions. If there is a key conflict we throw.
- */
- | 'DEFINE_MANY_MERGED';
-
-/**
- * Composite components are higher-level components that compose other composite
- * or host components.
- *
- * To create a new type of `ReactClass`, pass a specification of
- * your new class to `React.createClass`. The only requirement of your class
- * specification is that you implement a `render` method.
- *
- * var MyComponent = React.createClass({
- * render: function() {
- * return
Hello World
;
- * }
- * });
- *
- * The class specification supports a specific protocol of methods that have
- * special meaning (e.g. `render`). See `ReactClassInterface` for
- * more the comprehensive protocol. Any other properties and methods in the
- * class specification will be available on the prototype.
- *
- * @interface ReactClassInterface
- * @internal
- */
-var ReactClassInterface: {[key: string]: SpecPolicy} = {
- /**
- * An array of Mixin objects to include when defining your component.
- *
- * @type {array}
- * @optional
- */
- mixins: 'DEFINE_MANY',
-
- /**
- * An object containing properties and methods that should be defined on
- * the component's constructor instead of its prototype (static methods).
- *
- * @type {object}
- * @optional
- */
- statics: 'DEFINE_MANY',
-
- /**
- * Definition of prop types for this component.
- *
- * @type {object}
- * @optional
- */
- propTypes: 'DEFINE_MANY',
-
- /**
- * Definition of context types for this component.
- *
- * @type {object}
- * @optional
- */
- contextTypes: 'DEFINE_MANY',
-
- /**
- * Definition of context types this component sets for its children.
- *
- * @type {object}
- * @optional
- */
- childContextTypes: 'DEFINE_MANY',
-
- // ==== Definition methods ====
-
- /**
- * Invoked when the component is mounted. Values in the mapping will be set on
- * `this.props` if that prop is not specified (i.e. using an `in` check).
- *
- * This method is invoked before `getInitialState` and therefore cannot rely
- * on `this.state` or use `this.setState`.
- *
- * @return {object}
- * @optional
- */
- getDefaultProps: 'DEFINE_MANY_MERGED',
-
- /**
- * Invoked once before the component is mounted. The return value will be used
- * as the initial value of `this.state`.
- *
- * getInitialState: function() {
- * return {
- * isOn: false,
- * fooBaz: new BazFoo()
- * }
- * }
- *
- * @return {object}
- * @optional
- */
- getInitialState: 'DEFINE_MANY_MERGED',
-
- /**
- * @return {object}
- * @optional
- */
- getChildContext: 'DEFINE_MANY_MERGED',
-
- /**
- * Uses props from `this.props` and state from `this.state` to render the
- * structure of the component.
- *
- * No guarantees are made about when or how often this method is invoked, so
- * it must not have side effects.
- *
- * render: function() {
- * var name = this.props.name;
- * return Hello, {name}!
;
- * }
- *
- * @return {ReactComponent}
- * @required
- */
- render: 'DEFINE_ONCE',
-
- // ==== Delegate methods ====
-
- /**
- * Invoked when the component is initially created and about to be mounted.
- * This may have side effects, but any external subscriptions or data created
- * by this method must be cleaned up in `componentWillUnmount`.
- *
- * @optional
- */
- componentWillMount: 'DEFINE_MANY',
-
- /**
- * Invoked when the component has been mounted and has a DOM representation.
- * However, there is no guarantee that the DOM node is in the document.
- *
- * Use this as an opportunity to operate on the DOM when the component has
- * been mounted (initialized and rendered) for the first time.
- *
- * @param {DOMElement} rootNode DOM element representing the component.
- * @optional
- */
- componentDidMount: 'DEFINE_MANY',
-
- /**
- * Invoked before the component receives new props.
- *
- * Use this as an opportunity to react to a prop transition by updating the
- * state using `this.setState`. Current props are accessed via `this.props`.
- *
- * componentWillReceiveProps: function(nextProps, nextContext) {
- * this.setState({
- * likesIncreasing: nextProps.likeCount > this.props.likeCount
- * });
- * }
- *
- * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
- * transition may cause a state change, but the opposite is not true. If you
- * need it, you are probably looking for `componentWillUpdate`.
- *
- * @param {object} nextProps
- * @optional
- */
- componentWillReceiveProps: 'DEFINE_MANY',
-
- /**
- * Invoked while deciding if the component should be updated as a result of
- * receiving new props, state and/or context.
- *
- * Use this as an opportunity to `return false` when you're certain that the
- * transition to the new props/state/context will not require a component
- * update.
- *
- * shouldComponentUpdate: function(nextProps, nextState, nextContext) {
- * return !equal(nextProps, this.props) ||
- * !equal(nextState, this.state) ||
- * !equal(nextContext, this.context);
- * }
- *
- * @param {object} nextProps
- * @param {?object} nextState
- * @param {?object} nextContext
- * @return {boolean} True if the component should update.
- * @optional
- */
- shouldComponentUpdate: 'DEFINE_ONCE',
-
- /**
- * Invoked when the component is about to update due to a transition from
- * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
- * and `nextContext`.
- *
- * Use this as an opportunity to perform preparation before an update occurs.
- *
- * NOTE: You **cannot** use `this.setState()` in this method.
- *
- * @param {object} nextProps
- * @param {?object} nextState
- * @param {?object} nextContext
- * @param {ReactReconcileTransaction} transaction
- * @optional
- */
- componentWillUpdate: 'DEFINE_MANY',
-
- /**
- * Invoked when the component's DOM representation has been updated.
- *
- * Use this as an opportunity to operate on the DOM when the component has
- * been updated.
- *
- * @param {object} prevProps
- * @param {?object} prevState
- * @param {?object} prevContext
- * @param {DOMElement} rootNode DOM element representing the component.
- * @optional
- */
- componentDidUpdate: 'DEFINE_MANY',
-
- /**
- * Invoked when the component is about to be removed from its parent and have
- * its DOM representation destroyed.
- *
- * Use this as an opportunity to deallocate any external resources.
- *
- * NOTE: There is no `componentDidUnmount` since your component will have been
- * destroyed by that point.
- *
- * @optional
- */
- componentWillUnmount: 'DEFINE_MANY',
-
- // ==== Advanced methods ====
-
- /**
- * Updates the component's currently mounted DOM representation.
- *
- * By default, this implements React's rendering and reconciliation algorithm.
- * Sophisticated clients may wish to override this.
- *
- * @param {ReactReconcileTransaction} transaction
- * @internal
- * @overridable
- */
- updateComponent: 'OVERRIDE_BASE',
-};
-
-/**
- * Mapping from class specification keys to special processing functions.
- *
- * Although these are declared like instance properties in the specification
- * when defining classes using `React.createClass`, they are actually static
- * and are accessible on the constructor instead of the prototype. Despite
- * being static, they must be defined outside of the "statics" key under
- * which all other static methods are defined.
- */
-var RESERVED_SPEC_KEYS = {
- displayName: function(Constructor, displayName) {
- Constructor.displayName = displayName;
- },
- mixins: function(Constructor, mixins) {
- if (mixins) {
- for (var i = 0; i < mixins.length; i++) {
- mixSpecIntoComponent(Constructor, mixins[i]);
- }
- }
- },
- childContextTypes: function(Constructor, childContextTypes) {
- if (__DEV__) {
- validateTypeDef(Constructor, childContextTypes, 'child context');
- }
- Constructor.childContextTypes = Object.assign(
- {},
- Constructor.childContextTypes,
- childContextTypes,
- );
- },
- contextTypes: function(Constructor, contextTypes) {
- if (__DEV__) {
- validateTypeDef(Constructor, contextTypes, 'context');
- }
- Constructor.contextTypes = Object.assign(
- {},
- Constructor.contextTypes,
- contextTypes,
- );
- },
- /**
- * Special case getDefaultProps which should move into statics but requires
- * automatic merging.
- */
- getDefaultProps: function(Constructor, getDefaultProps) {
- if (Constructor.getDefaultProps) {
- Constructor.getDefaultProps = createMergedResultFunction(
- Constructor.getDefaultProps,
- getDefaultProps,
- );
- } else {
- Constructor.getDefaultProps = getDefaultProps;
- }
- },
- propTypes: function(Constructor, propTypes) {
- if (__DEV__) {
- validateTypeDef(Constructor, propTypes, 'prop');
- }
- Constructor.propTypes = Object.assign({}, Constructor.propTypes, propTypes);
- },
- statics: function(Constructor, statics) {
- mixStaticSpecIntoComponent(Constructor, statics);
- },
- autobind: function() {}, // noop
-};
-
-function validateTypeDef(Constructor, typeDef, location: string) {
- for (var propName in typeDef) {
- if (typeDef.hasOwnProperty(propName)) {
- // use a warning instead of an invariant so components
- // don't show up in prod but only in __DEV__
- warning(
- typeof typeDef[propName] === 'function',
- '%s: %s type `%s` is invalid; it must be a function, usually from ' +
- 'React.PropTypes.',
- Constructor.displayName || 'ReactClass',
- location,
- propName,
- );
- }
- }
-}
-
-function validateMethodOverride(isAlreadyDefined, name) {
- var specPolicy = ReactClassInterface.hasOwnProperty(name)
- ? ReactClassInterface[name]
- : null;
-
- // Disallow overriding of base class methods unless explicitly allowed.
- if (ReactClassMixin.hasOwnProperty(name)) {
- invariant(
- specPolicy === 'OVERRIDE_BASE',
- 'ReactClassInterface: You are attempting to override ' +
- '`%s` from your class specification. Ensure that your method names ' +
- 'do not overlap with React methods.',
- name,
- );
- }
-
- // Disallow defining methods more than once unless explicitly allowed.
- if (isAlreadyDefined) {
- invariant(
- specPolicy === 'DEFINE_MANY' || specPolicy === 'DEFINE_MANY_MERGED',
- 'ReactClassInterface: You are attempting to define ' +
- '`%s` on your component more than once. This conflict may be due ' +
- 'to a mixin.',
- name,
- );
- }
-}
-
-/**
- * Mixin helper which handles policy validation and reserved
- * specification keys when building React classes.
- */
-function mixSpecIntoComponent(Constructor, spec) {
- if (!spec) {
- if (__DEV__) {
- var typeofSpec = typeof spec;
- var isMixinValid = typeofSpec === 'object' && spec !== null;
-
- warning(
- isMixinValid,
- "%s: You're attempting to include a mixin that is either null " +
- 'or not an object. Check the mixins included by the component, ' +
- 'as well as any mixins they include themselves. ' +
- 'Expected object but got %s.',
- Constructor.displayName || 'ReactClass',
- spec === null ? null : typeofSpec,
- );
- }
-
- return;
- }
-
- invariant(
- typeof spec !== 'function',
- "ReactClass: You're attempting to " +
- 'use a component class or function as a mixin. Instead, just use a ' +
- 'regular object.',
- );
- invariant(
- !ReactElement.isValidElement(spec),
- "ReactClass: You're attempting to " +
- 'use a component as a mixin. Instead, just use a regular object.',
- );
-
- var proto = Constructor.prototype;
- var autoBindPairs = proto.__reactAutoBindPairs;
-
- // By handling mixins before any other properties, we ensure the same
- // chaining order is applied to methods with DEFINE_MANY policy, whether
- // mixins are listed before or after these methods in the spec.
- if (spec.hasOwnProperty(MIXINS_KEY)) {
- RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
- }
-
- for (var name in spec) {
- if (!spec.hasOwnProperty(name)) {
- continue;
- }
-
- if (name === MIXINS_KEY) {
- // We have already handled mixins in a special case above.
- continue;
- }
-
- var property = spec[name];
- var isAlreadyDefined = proto.hasOwnProperty(name);
- validateMethodOverride(isAlreadyDefined, name);
-
- if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
- RESERVED_SPEC_KEYS[name](Constructor, property);
- } else {
- // Setup methods on prototype:
- // The following member methods should not be automatically bound:
- // 1. Expected ReactClass methods (in the "interface").
- // 2. Overridden methods (that were mixed in).
- var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
- var isFunction = typeof property === 'function';
- var shouldAutoBind = isFunction &&
- !isReactClassMethod &&
- !isAlreadyDefined &&
- spec.autobind !== false;
-
- if (shouldAutoBind) {
- autoBindPairs.push(name, property);
- proto[name] = property;
- } else {
- if (isAlreadyDefined) {
- var specPolicy = ReactClassInterface[name];
-
- // These cases should already be caught by validateMethodOverride.
- invariant(
- isReactClassMethod &&
- (specPolicy === 'DEFINE_MANY_MERGED' ||
- specPolicy === 'DEFINE_MANY'),
- 'ReactClass: Unexpected spec policy %s for key %s ' +
- 'when mixing in component specs.',
- specPolicy,
- name,
- );
-
- // For methods which are defined more than once, call the existing
- // methods before calling the new property, merging if appropriate.
- if (specPolicy === 'DEFINE_MANY_MERGED') {
- proto[name] = createMergedResultFunction(proto[name], property);
- } else if (specPolicy === 'DEFINE_MANY') {
- proto[name] = createChainedFunction(proto[name], property);
- }
- } else {
- proto[name] = property;
- if (__DEV__) {
- // Add verbose displayName to the function, which helps when looking
- // at profiling tools.
- if (typeof property === 'function' && spec.displayName) {
- proto[name].displayName = spec.displayName + '_' + name;
- }
- }
- }
- }
- }
- }
-}
-
-function mixStaticSpecIntoComponent(Constructor, statics) {
- if (!statics) {
- return;
- }
- for (var name in statics) {
- var property = statics[name];
- if (!statics.hasOwnProperty(name)) {
- continue;
- }
-
- var isReserved = name in RESERVED_SPEC_KEYS;
- invariant(
- !isReserved,
- 'ReactClass: You are attempting to define a reserved ' +
- 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
- 'as an instance property instead; it will still be accessible on the ' +
- 'constructor.',
- name,
- );
-
- var isInherited = name in Constructor;
- invariant(
- !isInherited,
- 'ReactClass: You are attempting to define ' +
- '`%s` on your component more than once. This conflict may be ' +
- 'due to a mixin.',
- name,
- );
- Constructor[name] = property;
- }
-}
-
-/**
- * Merge two objects, but throw if both contain the same key.
- *
- * @param {object} one The first object, which is mutated.
- * @param {object} two The second object
- * @return {object} one after it has been mutated to contain everything in two.
- */
-function mergeIntoWithNoDuplicateKeys(one, two) {
- invariant(
- one && two && typeof one === 'object' && typeof two === 'object',
- 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.',
- );
-
- for (var key in two) {
- if (two.hasOwnProperty(key)) {
- invariant(
- one[key] === undefined,
- 'mergeIntoWithNoDuplicateKeys(): ' +
- 'Tried to merge two objects with the same key: `%s`. This conflict ' +
- 'may be due to a mixin; in particular, this may be caused by two ' +
- 'getInitialState() or getDefaultProps() methods returning objects ' +
- 'with clashing keys.',
- key,
- );
- one[key] = two[key];
- }
- }
- return one;
-}
-
-/**
- * Creates a function that invokes two functions and merges their return values.
- *
- * @param {function} one Function to invoke first.
- * @param {function} two Function to invoke second.
- * @return {function} Function that invokes the two argument functions.
- * @private
- */
-function createMergedResultFunction(one, two) {
- return function mergedResult() {
- var a = one.apply(this, arguments);
- var b = two.apply(this, arguments);
- if (a == null) {
- return b;
- } else if (b == null) {
- return a;
- }
- var c = {};
- mergeIntoWithNoDuplicateKeys(c, a);
- mergeIntoWithNoDuplicateKeys(c, b);
- return c;
- };
-}
-
-/**
- * Creates a function that invokes two functions and ignores their return vales.
- *
- * @param {function} one Function to invoke first.
- * @param {function} two Function to invoke second.
- * @return {function} Function that invokes the two argument functions.
- * @private
- */
-function createChainedFunction(one, two) {
- return function chainedFunction() {
- one.apply(this, arguments);
- two.apply(this, arguments);
- };
-}
-
-/**
- * Binds a method to the component.
- *
- * @param {object} component Component whose method is going to be bound.
- * @param {function} method Method to be bound.
- * @return {function} The bound method.
- */
-function bindAutoBindMethod(component, method) {
- var boundMethod = method.bind(component);
- if (__DEV__) {
- boundMethod.__reactBoundContext = component;
- boundMethod.__reactBoundMethod = method;
- boundMethod.__reactBoundArguments = null;
- var componentName = component.constructor.displayName;
- var _bind = boundMethod.bind;
- boundMethod.bind = function(newThis, ...args) {
- // User is trying to bind() an autobound method; we effectively will
- // ignore the value of "this" that the user is trying to use, so
- // let's warn.
- if (newThis !== component && newThis !== null) {
- warning(
- false,
- 'bind(): React component methods may only be bound to the ' +
- 'component instance.\n\nSee %s',
- componentName,
- );
- } else if (!args.length) {
- warning(
- false,
- 'bind(): You are binding a component method to the component. ' +
- 'React does this for you automatically in a high-performance ' +
- 'way, so you can safely remove this call.\n\nSee %s',
- componentName,
- );
- return boundMethod;
- }
- var reboundMethod = _bind.apply(boundMethod, arguments);
- reboundMethod.__reactBoundContext = component;
- reboundMethod.__reactBoundMethod = method;
- reboundMethod.__reactBoundArguments = args;
- return reboundMethod;
- };
- }
- return boundMethod;
-}
-
-/**
- * Binds all auto-bound methods in a component.
- *
- * @param {object} component Component whose method is going to be bound.
- */
-function bindAutoBindMethods(component) {
- var pairs = component.__reactAutoBindPairs;
- for (var i = 0; i < pairs.length; i += 2) {
- var autoBindKey = pairs[i];
- var method = pairs[i + 1];
- component[autoBindKey] = bindAutoBindMethod(component, method);
- }
-}
-
-/**
- * Add more to the ReactClass base class. These are all legacy features and
- * therefore not already part of the modern ReactComponent.
- */
-var ReactClassMixin = {
- /**
- * TODO: This will be deprecated because state should always keep a consistent
- * type signature and the only use case for this, is to avoid that.
- */
- replaceState: function(newState, callback) {
- this.updater.enqueueReplaceState(this, newState, callback, 'replaceState');
- },
-
- /**
- * Checks whether or not this composite component is mounted.
- * @return {boolean} True if mounted, false otherwise.
- * @protected
- * @final
- */
- isMounted: function() {
- return this.updater.isMounted(this);
- },
-};
-
-var ReactClassComponent = function() {};
-Object.assign(
- ReactClassComponent.prototype,
- ReactComponent.prototype,
- ReactClassMixin,
-);
-
-/**
- * Module for creating composite components.
- *
- * @class ReactClass
- */
-var ReactClass = {
- /**
- * Creates a composite component class given a class specification.
- * See https://facebook.github.io/react/docs/react-api.html#createclass
- *
- * @param {object} spec Class specification (which must define `render`).
- * @return {function} Component constructor function.
- * @public
- */
- createClass: function(spec) {
- // To keep our warnings more understandable, we'll use a little hack here to
- // ensure that Constructor.name !== 'Constructor'. This makes sure we don't
- // unnecessarily identify a class without displayName as 'Constructor'.
- var Constructor = identity(function(props, context, updater) {
- // This constructor gets overridden by mocks. The argument is used
- // by mocks to assert on what gets mounted.
-
- if (__DEV__) {
- warning(
- this instanceof Constructor,
- 'Something is calling a React component directly. Use a factory or ' +
- 'JSX instead. See: https://fb.me/react-legacyfactory',
- );
- }
-
- // Wire up auto-binding
- if (this.__reactAutoBindPairs.length) {
- bindAutoBindMethods(this);
- }
-
- this.props = props;
- this.context = context;
- this.refs = emptyObject;
- this.updater = updater || ReactNoopUpdateQueue;
-
- this.state = null;
-
- // ReactClasses doesn't have constructors. Instead, they use the
- // getInitialState and componentWillMount methods for initialization.
-
- var initialState = this.getInitialState ? this.getInitialState() : null;
- if (__DEV__) {
- // We allow auto-mocks to proceed as if they're returning null.
- if (
- initialState === undefined && this.getInitialState._isMockFunction
- ) {
- // This is probably bad practice. Consider warning here and
- // deprecating this convenience.
- initialState = null;
- }
- }
- invariant(
- typeof initialState === 'object' && !Array.isArray(initialState),
- '%s.getInitialState(): must return an object or null',
- Constructor.displayName || 'ReactCompositeComponent',
- );
-
- this.state = initialState;
- });
- Constructor.prototype = new ReactClassComponent();
- Constructor.prototype.constructor = Constructor;
- Constructor.prototype.__reactAutoBindPairs = [];
-
- mixSpecIntoComponent(Constructor, spec);
-
- // Initialize the defaultProps property after all mixins have been merged.
- if (Constructor.getDefaultProps) {
- Constructor.defaultProps = Constructor.getDefaultProps();
- }
-
- if (__DEV__) {
- // This is a tag to indicate that the use of these method names is ok,
- // since it's used with createClass. If it's not, then it's likely a
- // mistake so we'll warn you to use the static property, property
- // initializer or constructor respectively.
- if (Constructor.getDefaultProps) {
- Constructor.getDefaultProps.isReactClassApproved = {};
- }
- if (Constructor.prototype.getInitialState) {
- Constructor.prototype.getInitialState.isReactClassApproved = {};
- }
- }
-
- invariant(
- Constructor.prototype.render,
- 'createClass(...): Class specification must implement a `render` method.',
- );
-
- if (__DEV__) {
- warning(
- !Constructor.prototype.componentShouldUpdate,
- '%s has a method called ' +
- 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
- 'The name is phrased as a question because the function is ' +
- 'expected to return a value.',
- spec.displayName || 'A component',
- );
- warning(
- !Constructor.prototype.componentWillRecieveProps,
- '%s has a method called ' +
- 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
- spec.displayName || 'A component',
- );
- }
-
- // Reduce time spent doing lookups by setting these on the prototype.
- for (var methodName in ReactClassInterface) {
- if (!Constructor.prototype[methodName]) {
- Constructor.prototype[methodName] = null;
- }
- }
-
- return Constructor;
- },
-};
-
-module.exports = ReactClass;
diff --git a/src/isomorphic/classic/class/__tests__/ReactBind-test.js b/src/isomorphic/classic/class/__tests__/ReactBind-test.js
deleted file mode 100644
index 051db5a8fe..0000000000
--- a/src/isomorphic/classic/class/__tests__/ReactBind-test.js
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @emails react-core
- */
-/*global global:true*/
-'use strict';
-
-var React = require('react');
-var ReactTestUtils = require('ReactTestUtils');
-
-// TODO: Test render and all stock methods.
-describe('autobinding', () => {
- it('Holds reference to instance', () => {
- var mouseDidEnter = jest.fn();
- var mouseDidLeave = jest.fn();
- var mouseDidClick = jest.fn();
-
- var TestBindComponent = React.createClass({
- getInitialState: function() {
- return {something: 'hi'};
- },
- onMouseEnter: mouseDidEnter,
- onMouseLeave: mouseDidLeave,
- onClick: mouseDidClick,
-
- // auto binding only occurs on top level functions in class defs.
- badIdeas: {
- badBind: function() {
- void this.state.something;
- },
- },
-
- render: function() {
- return (
-
- );
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- var instance2 = ReactTestUtils.renderIntoDocument();
- var rendered2 = instance2.refs.child;
-
- expect(function() {
- var badIdea = instance1.badIdeas.badBind;
- badIdea();
- }).toThrow();
-
- expect(instance1.onClick).not.toBe(instance2.onClick);
-
- ReactTestUtils.Simulate.click(rendered1);
- expect(mouseDidClick.mock.instances.length).toBe(1);
- expect(mouseDidClick.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.click(rendered2);
- expect(mouseDidClick.mock.instances.length).toBe(2);
- expect(mouseDidClick.mock.instances[1]).toBe(instance2);
-
- ReactTestUtils.Simulate.mouseOver(rendered1);
- expect(mouseDidEnter.mock.instances.length).toBe(1);
- expect(mouseDidEnter.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.mouseOver(rendered2);
- expect(mouseDidEnter.mock.instances.length).toBe(2);
- expect(mouseDidEnter.mock.instances[1]).toBe(instance2);
-
- ReactTestUtils.Simulate.mouseOut(rendered1);
- expect(mouseDidLeave.mock.instances.length).toBe(1);
- expect(mouseDidLeave.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.mouseOut(rendered2);
- expect(mouseDidLeave.mock.instances.length).toBe(2);
- expect(mouseDidLeave.mock.instances[1]).toBe(instance2);
- });
-
- it('works with mixins', () => {
- var mouseDidClick = jest.fn();
-
- var TestMixin = {
- onClick: mouseDidClick,
- };
-
- var TestBindComponent = React.createClass({
- mixins: [TestMixin],
-
- render: function() {
- return ;
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- ReactTestUtils.Simulate.click(rendered1);
- expect(mouseDidClick.mock.instances.length).toBe(1);
- expect(mouseDidClick.mock.instances[0]).toBe(instance1);
- });
-
- it('warns if you try to bind to this', () => {
- spyOn(console, 'error');
-
- var TestBindComponent = React.createClass({
- handleClick: function() {},
- render: function() {
- return ;
- },
- });
-
- ReactTestUtils.renderIntoDocument();
-
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: bind(): You are binding a component method to the component. ' +
- 'React does this for you automatically in a high-performance ' +
- 'way, so you can safely remove this call.\n\nSee TestBindComponent',
- );
- });
-
- it('does not warn if you pass an auto-bound method to setState', () => {
- spyOn(console, 'error');
-
- var TestBindComponent = React.createClass({
- getInitialState: function() {
- return {foo: 1};
- },
- componentDidMount: function() {
- this.setState({foo: 2}, this.handleUpdate);
- },
- handleUpdate: function() {},
- render: function() {
- return ;
- },
- });
-
- ReactTestUtils.renderIntoDocument();
-
- expectDev(console.error.calls.count()).toBe(0);
- });
-});
diff --git a/src/isomorphic/classic/class/__tests__/ReactBindOptout-test.js b/src/isomorphic/classic/class/__tests__/ReactBindOptout-test.js
deleted file mode 100644
index 086329338f..0000000000
--- a/src/isomorphic/classic/class/__tests__/ReactBindOptout-test.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @emails react-core
- */
-/*global global:true*/
-'use strict';
-
-var React = require('react');
-var ReactTestUtils = require('ReactTestUtils');
-
-// TODO: Test render and all stock methods.
-describe('autobind optout', () => {
- it('should work with manual binding', () => {
- var mouseDidEnter = jest.fn();
- var mouseDidLeave = jest.fn();
- var mouseDidClick = jest.fn();
-
- var TestBindComponent = React.createClass({
- autobind: false,
- getInitialState: function() {
- return {something: 'hi'};
- },
- onMouseEnter: mouseDidEnter,
- onMouseLeave: mouseDidLeave,
- onClick: mouseDidClick,
-
- render: function() {
- return (
-
- );
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- var instance2 = ReactTestUtils.renderIntoDocument();
- var rendered2 = instance2.refs.child;
-
- ReactTestUtils.Simulate.click(rendered1);
- expect(mouseDidClick.mock.instances.length).toBe(1);
- expect(mouseDidClick.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.click(rendered2);
- expect(mouseDidClick.mock.instances.length).toBe(2);
- expect(mouseDidClick.mock.instances[1]).toBe(instance2);
-
- ReactTestUtils.Simulate.mouseOver(rendered1);
- expect(mouseDidEnter.mock.instances.length).toBe(1);
- expect(mouseDidEnter.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.mouseOver(rendered2);
- expect(mouseDidEnter.mock.instances.length).toBe(2);
- expect(mouseDidEnter.mock.instances[1]).toBe(instance2);
-
- ReactTestUtils.Simulate.mouseOut(rendered1);
- expect(mouseDidLeave.mock.instances.length).toBe(1);
- expect(mouseDidLeave.mock.instances[0]).toBe(instance1);
-
- ReactTestUtils.Simulate.mouseOut(rendered2);
- expect(mouseDidLeave.mock.instances.length).toBe(2);
- expect(mouseDidLeave.mock.instances[1]).toBe(instance2);
- });
-
- it('should not hold reference to instance', () => {
- var mouseDidClick = function() {
- void this.state.something;
- };
-
- var TestBindComponent = React.createClass({
- autobind: false,
- getInitialState: function() {
- return {something: 'hi'};
- },
- onClick: mouseDidClick,
-
- // auto binding only occurs on top level functions in class defs.
- badIdeas: {
- badBind: function() {
- void this.state.something;
- },
- },
-
- render: function() {
- return ;
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- var instance2 = ReactTestUtils.renderIntoDocument();
- var rendered2 = instance2.refs.child;
-
- expect(function() {
- var badIdea = instance1.badIdeas.badBind;
- badIdea();
- }).toThrow();
-
- expect(instance1.onClick).toBe(instance2.onClick);
-
- expect(function() {
- ReactTestUtils.Simulate.click(rendered1);
- }).toThrow();
-
- expect(function() {
- ReactTestUtils.Simulate.click(rendered2);
- }).toThrow();
- });
-
- it('works with mixins that have not opted out of autobinding', () => {
- var mouseDidClick = jest.fn();
-
- var TestMixin = {
- onClick: mouseDidClick,
- };
-
- var TestBindComponent = React.createClass({
- mixins: [TestMixin],
-
- render: function() {
- return ;
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- ReactTestUtils.Simulate.click(rendered1);
- expect(mouseDidClick.mock.instances.length).toBe(1);
- expect(mouseDidClick.mock.instances[0]).toBe(instance1);
- });
-
- it('works with mixins that have opted out of autobinding', () => {
- var mouseDidClick = jest.fn();
-
- var TestMixin = {
- autobind: false,
- onClick: mouseDidClick,
- };
-
- var TestBindComponent = React.createClass({
- mixins: [TestMixin],
-
- render: function() {
- return ;
- },
- });
-
- var instance1 = ReactTestUtils.renderIntoDocument();
- var rendered1 = instance1.refs.child;
-
- ReactTestUtils.Simulate.click(rendered1);
- expect(mouseDidClick.mock.instances.length).toBe(1);
- expect(mouseDidClick.mock.instances[0]).toBe(instance1);
- });
-
- it('does not warn if you try to bind to this', () => {
- spyOn(console, 'error');
-
- var TestBindComponent = React.createClass({
- autobind: false,
- handleClick: function() {},
- render: function() {
- return ;
- },
- });
-
- ReactTestUtils.renderIntoDocument();
-
- expectDev(console.error.calls.count()).toBe(0);
- });
-
- it('does not warn if you pass an manually bound method to setState', () => {
- spyOn(console, 'error');
-
- var TestBindComponent = React.createClass({
- autobind: false,
- getInitialState: function() {
- return {foo: 1};
- },
- componentDidMount: function() {
- this.setState({foo: 2}, this.handleUpdate.bind(this));
- },
- handleUpdate: function() {},
- render: function() {
- return ;
- },
- });
-
- ReactTestUtils.renderIntoDocument();
-
- expectDev(console.error.calls.count()).toBe(0);
- });
-});
diff --git a/src/isomorphic/classic/class/__tests__/ReactClass-test.js b/src/isomorphic/classic/class/__tests__/ReactClass-test.js
deleted file mode 100644
index 4ab5ad7dac..0000000000
--- a/src/isomorphic/classic/class/__tests__/ReactClass-test.js
+++ /dev/null
@@ -1,348 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @emails react-core
- */
-
-'use strict';
-
-var React;
-var ReactDOM;
-var ReactTestUtils;
-
-describe('ReactClass-spec', () => {
- beforeEach(() => {
- React = require('react');
- ReactDOM = require('react-dom');
- ReactTestUtils = require('ReactTestUtils');
- });
-
- it('should throw when `render` is not specified', () => {
- expect(function() {
- React.createClass({});
- }).toThrowError(
- 'createClass(...): Class specification must implement a `render` method.',
- );
- });
-
- it('should copy `displayName` onto the Constructor', () => {
- var TestComponent = React.createClass({
- render: function() {
- return ;
- },
- });
-
- expect(TestComponent.displayName).toBe('TestComponent');
- });
-
- it('should copy prop types onto the Constructor', () => {
- var propValidator = jest.fn();
- var TestComponent = React.createClass({
- propTypes: {
- value: propValidator,
- },
- render: function() {
- return ;
- },
- });
-
- expect(TestComponent.propTypes).toBeDefined();
- expect(TestComponent.propTypes.value).toBe(propValidator);
- });
-
- it('should warn on invalid prop types', () => {
- spyOn(console, 'error');
- React.createClass({
- displayName: 'Component',
- propTypes: {
- prop: null,
- },
- render: function() {
- return {this.props.prop};
- },
- });
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component: prop type `prop` is invalid; ' +
- 'it must be a function, usually from React.PropTypes.',
- );
- });
-
- it('should warn on invalid context types', () => {
- spyOn(console, 'error');
- React.createClass({
- displayName: 'Component',
- contextTypes: {
- prop: null,
- },
- render: function() {
- return {this.props.prop};
- },
- });
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component: context type `prop` is invalid; ' +
- 'it must be a function, usually from React.PropTypes.',
- );
- });
-
- it('should throw on invalid child context types', () => {
- spyOn(console, 'error');
- React.createClass({
- displayName: 'Component',
- childContextTypes: {
- prop: null,
- },
- render: function() {
- return {this.props.prop};
- },
- });
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component: child context type `prop` is invalid; ' +
- 'it must be a function, usually from React.PropTypes.',
- );
- });
-
- it('should warn when mispelling shouldComponentUpdate', () => {
- spyOn(console, 'error');
-
- React.createClass({
- componentShouldUpdate: function() {
- return false;
- },
- render: function() {
- return ;
- },
- });
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: A component has a method called componentShouldUpdate(). Did you ' +
- 'mean shouldComponentUpdate()? The name is phrased as a question ' +
- 'because the function is expected to return a value.',
- );
-
- React.createClass({
- displayName: 'NamedComponent',
- componentShouldUpdate: function() {
- return false;
- },
- render: function() {
- return ;
- },
- });
- expectDev(console.error.calls.count()).toBe(2);
- expectDev(console.error.calls.argsFor(1)[0]).toBe(
- 'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
- 'mean shouldComponentUpdate()? The name is phrased as a question ' +
- 'because the function is expected to return a value.',
- );
- });
-
- it('should warn when mispelling componentWillReceiveProps', () => {
- spyOn(console, 'error');
- React.createClass({
- componentWillRecieveProps: function() {
- return false;
- },
- render: function() {
- return ;
- },
- });
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
- 'mean componentWillReceiveProps()?',
- );
- });
-
- it('should throw if a reserved property is in statics', () => {
- expect(function() {
- React.createClass({
- statics: {
- getDefaultProps: function() {
- return {
- foo: 0,
- };
- },
- },
-
- render: function() {
- return ;
- },
- });
- }).toThrowError(
- 'ReactClass: You are attempting to define a reserved property, ' +
- '`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
- 'it as an instance property instead; it will still be accessible on ' +
- 'the constructor.',
- );
- });
-
- // TODO: Consider actually moving these to statics or drop this unit test.
-
- xit('should warn when using deprecated non-static spec keys', () => {
- spyOn(console, 'error');
- React.createClass({
- mixins: [{}],
- propTypes: {
- foo: React.PropTypes.string,
- },
- contextTypes: {
- foo: React.PropTypes.string,
- },
- childContextTypes: {
- foo: React.PropTypes.string,
- },
- render: function() {
- return ;
- },
- });
- expectDev(console.error.calls.count()).toBe(4);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'createClass(...): `mixins` is now a static property and should ' +
- 'be defined inside "statics".',
- );
- expectDev(console.error.calls.argsFor(1)[0]).toBe(
- 'createClass(...): `propTypes` is now a static property and should ' +
- 'be defined inside "statics".',
- );
- expectDev(console.error.calls.argsFor(2)[0]).toBe(
- 'createClass(...): `contextTypes` is now a static property and ' +
- 'should be defined inside "statics".',
- );
- expectDev(console.error.calls.argsFor(3)[0]).toBe(
- 'createClass(...): `childContextTypes` is now a static property and ' +
- 'should be defined inside "statics".',
- );
- });
-
- it('should support statics', () => {
- var Component = React.createClass({
- statics: {
- abc: 'def',
- def: 0,
- ghi: null,
- jkl: 'mno',
- pqr: function() {
- return this;
- },
- },
-
- render: function() {
- return ;
- },
- });
- var instance = ;
- instance = ReactTestUtils.renderIntoDocument(instance);
- expect(instance.constructor.abc).toBe('def');
- expect(Component.abc).toBe('def');
- expect(instance.constructor.def).toBe(0);
- expect(Component.def).toBe(0);
- expect(instance.constructor.ghi).toBe(null);
- expect(Component.ghi).toBe(null);
- expect(instance.constructor.jkl).toBe('mno');
- expect(Component.jkl).toBe('mno');
- expect(instance.constructor.pqr()).toBe(Component);
- expect(Component.pqr()).toBe(Component);
- });
-
- it('should work with object getInitialState() return values', () => {
- var Component = React.createClass({
- getInitialState: function() {
- return {
- occupation: 'clown',
- };
- },
- render: function() {
- return ;
- },
- });
- var instance = ;
- instance = ReactTestUtils.renderIntoDocument(instance);
- expect(instance.state.occupation).toEqual('clown');
- });
-
- it('renders based on context getInitialState', () => {
- var Foo = React.createClass({
- contextTypes: {
- className: React.PropTypes.string,
- },
- getInitialState() {
- return {className: this.context.className};
- },
- render() {
- return ;
- },
- });
-
- var Outer = React.createClass({
- childContextTypes: {
- className: React.PropTypes.string,
- },
- getChildContext() {
- return {className: 'foo'};
- },
- render() {
- return ;
- },
- });
-
- var container = document.createElement('div');
- ReactDOM.render(, container);
- expect(container.firstChild.className).toBe('foo');
- });
-
- it('should throw with non-object getInitialState() return values', () => {
- [['an array'], 'a string', 1234].forEach(function(state) {
- var Component = React.createClass({
- getInitialState: function() {
- return state;
- },
- render: function() {
- return ;
- },
- });
- var instance = ;
- expect(function() {
- instance = ReactTestUtils.renderIntoDocument(instance);
- }).toThrowError(
- 'Component.getInitialState(): must return an object or null',
- );
- });
- });
-
- it('should work with a null getInitialState() return value', () => {
- var Component = React.createClass({
- getInitialState: function() {
- return null;
- },
- render: function() {
- return ;
- },
- });
- expect(() =>
- ReactTestUtils.renderIntoDocument()).not.toThrow();
- });
-
- it('should throw when using legacy factories', () => {
- spyOn(console, 'error');
- var Component = React.createClass({
- render() {
- return ;
- },
- });
-
- expect(() => Component()).toThrow();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Something is calling a React component directly. Use a ' +
- 'factory or JSX instead. See: https://fb.me/react-legacyfactory',
- );
- });
-});
diff --git a/src/isomorphic/classic/class/__tests__/ReactClassMixin-test.js b/src/isomorphic/classic/class/__tests__/ReactClassMixin-test.js
deleted file mode 100644
index 2f079a69fc..0000000000
--- a/src/isomorphic/classic/class/__tests__/ReactClassMixin-test.js
+++ /dev/null
@@ -1,532 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @emails react-core
- */
-
-'use strict';
-
-var React;
-var ReactTestUtils;
-
-var TestComponent;
-var TestComponentWithPropTypes;
-var TestComponentWithReverseSpec;
-var mixinPropValidator;
-var componentPropValidator;
-
-describe('ReactClass-mixin', () => {
- beforeEach(() => {
- React = require('react');
- ReactTestUtils = require('ReactTestUtils');
- mixinPropValidator = jest.fn();
- componentPropValidator = jest.fn();
-
- 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 MixinBWithReverseSpec = {
- componentDidMount: function() {
- this.props.listener('MixinBWithReverseSpec didMount');
- },
- mixins: [MixinA],
- };
-
- var MixinC = {
- statics: {
- staticC: function() {},
- },
- componentDidMount: function() {
- this.props.listener('MixinC didMount');
- },
- };
-
- var MixinD = {
- propTypes: {
- value: mixinPropValidator,
- },
- };
-
- TestComponent = React.createClass({
- mixins: [MixinB, MixinC, MixinD],
- statics: {
- staticComponent: function() {},
- },
- propTypes: {
- propComponent: function() {},
- },
- componentDidMount: function() {
- this.props.listener('Component didMount');
- },
- render: function() {
- return ;
- },
- });
-
- TestComponentWithReverseSpec = React.createClass({
- render: function() {
- return ;
- },
- componentDidMount: function() {
- this.props.listener('Component didMount');
- },
- mixins: [MixinBWithReverseSpec, MixinC, MixinD],
- });
-
- TestComponentWithPropTypes = React.createClass({
- mixins: [MixinD],
- propTypes: {
- value: componentPropValidator,
- },
- render: function() {
- return ;
- },
- });
- });
-
- it('should support merging propTypes and statics', () => {
- var listener = jest.fn();
- var instance = ;
- instance = 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', () => {
- var listener = jest.fn();
- var instance = ;
- ReactTestUtils.renderIntoDocument(instance);
-
- expect(listener.mock.calls).toEqual([
- ['MixinA didMount'],
- ['MixinB didMount'],
- ['MixinC didMount'],
- ['Component didMount'],
- ]);
- });
-
- it('should chain functions regardless of spec property order', () => {
- var listener = jest.fn();
- var instance = ;
- ReactTestUtils.renderIntoDocument(instance);
-
- expect(listener.mock.calls).toEqual([
- ['MixinA didMount'],
- ['MixinBWithReverseSpec didMount'],
- ['MixinC didMount'],
- ['Component didMount'],
- ]);
- });
-
- it('should validate prop types via mixins', () => {
- expect(TestComponent.propTypes).toBeDefined();
- expect(TestComponent.propTypes.value).toBe(mixinPropValidator);
- });
-
- it('should override mixin prop types with class prop types', () => {
- // Sanity check...
- expect(componentPropValidator).not.toBe(mixinPropValidator);
- // Actually check...
- expect(TestComponentWithPropTypes.propTypes).toBeDefined();
- expect(TestComponentWithPropTypes.propTypes.value).not.toBe(
- mixinPropValidator,
- );
- expect(TestComponentWithPropTypes.propTypes.value).toBe(
- componentPropValidator,
- );
- });
-
- it('should support mixins with getInitialState()', () => {
- var Mixin = {
- getInitialState: function() {
- return {mixin: true};
- },
- };
- var Component = React.createClass({
- mixins: [Mixin],
- getInitialState: function() {
- return {component: true};
- },
- render: function() {
- return ;
- },
- });
- var instance = ReactTestUtils.renderIntoDocument();
- expect(instance.state.component).toBe(true);
- expect(instance.state.mixin).toBe(true);
- });
-
- it('should throw with conflicting getInitialState() methods', () => {
- var Mixin = {
- getInitialState: function() {
- return {x: true};
- },
- };
- var Component = React.createClass({
- mixins: [Mixin],
- getInitialState: function() {
- return {x: true};
- },
- render: function() {
- return ;
- },
- });
- expect(function() {
- ReactTestUtils.renderIntoDocument();
- }).toThrowError(
- 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the ' +
- 'same key: `x`. This conflict may be due to a mixin; in particular, ' +
- 'this may be caused by two getInitialState() or getDefaultProps() ' +
- 'methods returning objects with clashing keys.',
- );
- });
-
- it('should not mutate objects returned by getInitialState()', () => {
- var Mixin = {
- getInitialState: function() {
- return Object.freeze({mixin: true});
- },
- };
- var Component = React.createClass({
- mixins: [Mixin],
- getInitialState: function() {
- return Object.freeze({component: true});
- },
- render: function() {
- return ;
- },
- });
- expect(() => {
- ReactTestUtils.renderIntoDocument();
- }).not.toThrow();
- });
-
- it('should support statics in mixins', () => {
- var Mixin = {
- statics: {
- foo: 'bar',
- },
- };
- var Component = React.createClass({
- mixins: [Mixin],
-
- statics: {
- abc: 'def',
- },
-
- render: function() {
- return ;
- },
- });
- var instance = ;
- instance = ReactTestUtils.renderIntoDocument(instance);
- expect(instance.constructor.foo).toBe('bar');
- expect(Component.foo).toBe('bar');
- expect(instance.constructor.abc).toBe('def');
- expect(Component.abc).toBe('def');
- });
-
- it("should throw if mixins override each others' statics", () => {
- expect(function() {
- var Mixin = {
- statics: {
- abc: 'foo',
- },
- };
- React.createClass({
- mixins: [Mixin],
-
- statics: {
- abc: 'bar',
- },
-
- render: function() {
- return ;
- },
- });
- }).toThrowError(
- 'ReactClass: You are attempting to define `abc` on your component more ' +
- 'than once. This conflict may be due to a mixin.',
- );
- });
-
- it('should throw if mixins override functions in statics', () => {
- expect(function() {
- var Mixin = {
- statics: {
- abc: function() {
- console.log('foo');
- },
- },
- };
- React.createClass({
- mixins: [Mixin],
-
- statics: {
- abc: function() {
- console.log('bar');
- },
- },
-
- render: function() {
- return ;
- },
- });
- }).toThrowError(
- 'ReactClass: You are attempting to define `abc` on your component ' +
- 'more than once. This conflict may be due to a mixin.',
- );
- });
-
- it('should warn if the mixin is undefined', () => {
- spyOn(console, 'error');
-
- React.createClass({
- mixins: [undefined],
-
- render: function() {
- return ;
- },
- });
-
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- "Warning: ReactClass: You're attempting to include a mixin that is " +
- 'either null or not an object. Check the mixins included by the ' +
- 'component, as well as any mixins they include themselves. ' +
- 'Expected object but got undefined.',
- );
- });
-
- it('should warn if the mixin is null', () => {
- spyOn(console, 'error');
-
- React.createClass({
- mixins: [null],
-
- render: function() {
- return ;
- },
- });
-
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- "Warning: ReactClass: You're attempting to include a mixin that is " +
- 'either null or not an object. Check the mixins included by the ' +
- 'component, as well as any mixins they include themselves. ' +
- 'Expected object but got null.',
- );
- });
-
- it('should warn if an undefined mixin is included in another mixin', () => {
- spyOn(console, 'error');
-
- var mixinA = {
- mixins: [undefined],
- };
-
- React.createClass({
- mixins: [mixinA],
-
- render: function() {
- return ;
- },
- });
-
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- "Warning: ReactClass: You're attempting to include a mixin that is " +
- 'either null or not an object. Check the mixins included by the ' +
- 'component, as well as any mixins they include themselves. ' +
- 'Expected object but got undefined.',
- );
- });
-
- it('should warn if a null mixin is included in another mixin', () => {
- spyOn(console, 'error');
-
- var mixinA = {
- mixins: [null],
- };
-
- React.createClass({
- mixins: [mixinA],
-
- render: function() {
- return ;
- },
- });
-
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- "Warning: ReactClass: You're attempting to include a mixin that is " +
- 'either null or not an object. Check the mixins included by the ' +
- 'component, as well as any mixins they include themselves. ' +
- 'Expected object but got null.',
- );
- });
-
- it('should throw if the mixin is a React component', () => {
- expect(function() {
- React.createClass({
- mixins: [],
-
- render: function() {
- return ;
- },
- });
- }).toThrowError(
- "ReactClass: 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', () => {
- expect(function() {
- var Component = React.createClass({
- render: function() {
- return ;
- },
- });
-
- React.createClass({
- mixins: [Component],
-
- render: function() {
- return ;
- },
- });
- }).toThrowError(
- "ReactClass: You're attempting to use a component class or function " +
- 'as a mixin. Instead, just use a regular object.',
- );
- });
-
- it('should have bound the mixin methods to the component', () => {
- var mixin = {
- mixinFunc: function() {
- return this;
- },
- };
-
- var Component = React.createClass({
- mixins: [mixin],
- componentDidMount: function() {
- expect(this.mixinFunc()).toBe(this);
- },
- render: function() {
- return ;
- },
- });
- ReactTestUtils.renderIntoDocument();
- });
-
- it('should include the mixin keys in even if their values are falsy', () => {
- var mixin = {
- keyWithNullValue: null,
- randomCounter: 0,
- };
-
- var Component = React.createClass({
- mixins: [mixin],
- componentDidMount: function() {
- expect(this.randomCounter).toBe(0);
- expect(this.keyWithNullValue).toBeNull();
- },
- render: function() {
- return ;
- },
- });
- ReactTestUtils.renderIntoDocument();
- });
-
- it('should work with a null getInitialState return value and a mixin', () => {
- var Component;
- var instance;
-
- var Mixin = {
- getInitialState: function() {
- return {foo: 'bar'};
- },
- };
- Component = React.createClass({
- mixins: [Mixin],
- getInitialState: function() {
- return null;
- },
- render: function() {
- return ;
- },
- });
- expect(() =>
- ReactTestUtils.renderIntoDocument()).not.toThrow();
-
- instance = ReactTestUtils.renderIntoDocument();
- expect(instance.state).toEqual({foo: 'bar'});
-
- // Also the other way round should work
- var Mixin2 = {
- getInitialState: function() {
- return null;
- },
- };
- Component = React.createClass({
- mixins: [Mixin2],
- getInitialState: function() {
- return {foo: 'bar'};
- },
- render: function() {
- return ;
- },
- });
- expect(() =>
- ReactTestUtils.renderIntoDocument()).not.toThrow();
-
- instance = ReactTestUtils.renderIntoDocument();
- expect(instance.state).toEqual({foo: 'bar'});
-
- // Multiple mixins should be fine too
- Component = React.createClass({
- mixins: [Mixin, Mixin2],
- getInitialState: function() {
- return {x: true};
- },
- render: function() {
- return ;
- },
- });
- expect(() =>
- ReactTestUtils.renderIntoDocument()).not.toThrow();
-
- instance = ReactTestUtils.renderIntoDocument();
- expect(instance.state).toEqual({foo: 'bar', x: true});
- });
-});