@samitouri / QOS-React / commits / 5cfaa7cf68

Delete createClass

Remove createClass from isomorphic package

Andrew Clark committed Mar 21, 2017 at 18:36 UTC 5cfaa7cf68564b8d96c94fa0d45e7feb6dc80895
6 files changed -2073
src/isomorphic/React.js
-2
@@ -13,7 +13,6 @@
13
14 var ReactBaseClasses = require('ReactBaseClasses');
15 var ReactChildren = require('ReactChildren');
16 -var ReactClass = require('ReactClass');
16 var ReactDOMFactories = require('ReactDOMFactories');
17 var ReactElement = require('ReactElement');
18 var ReactPropTypes = require('ReactPropTypes');
@@ -75,7 +74,6 @@ var React = {
74 // Classic
75
76 PropTypes: ReactPropTypes,
78 - createClass: ReactClass.createClass,
77 createFactory: createFactory,
78 createMixin: createMixin,
79
src/isomorphic/classic/class/ReactClass.js deleted
-833
@@ -1,833 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @providesModule ReactClass
10 - */
11 -
12 -'use strict';
13 -
14 -var ReactBaseClasses = require('ReactBaseClasses');
15 -var ReactElement = require('ReactElement');
16 -var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');
17 -
18 -var emptyObject = require('fbjs/lib/emptyObject');
19 -var invariant = require('fbjs/lib/invariant');
20 -var warning = require('fbjs/lib/warning');
21 -
22 -var ReactComponent = ReactBaseClasses.Component;
23 -
24 -var MIXINS_KEY = 'mixins';
25 -
26 -// Helper function to allow the creation of anonymous functions which do not
27 -// have .name set to the name of the variable being assigned to.
28 -function identity(fn) {
29 - return fn;
30 -}
31 -
32 -/**
33 - * Policies that describe methods in `ReactClassInterface`.
34 - */
35 -type SpecPolicy =
36 - /**
37 - * These methods may be defined only once by the class specification or mixin.
38 - */
39 - | 'DEFINE_ONCE' /**
40 - * These methods may be defined by both the class specification and mixins.
41 - * Subsequent definitions will be chained. These methods must return void.
42 - */
43 - | 'DEFINE_MANY' /**
44 - * These methods are overriding the base class.
45 - */
46 - | 'OVERRIDE_BASE' /**
47 - * These methods are similar to DEFINE_MANY, except we assume they return
48 - * objects. We try to merge the keys of the return values of all the mixed in
49 - * functions. If there is a key conflict we throw.
50 - */
51 - | 'DEFINE_MANY_MERGED';
52 -
53 -/**
54 - * Composite components are higher-level components that compose other composite
55 - * or host components.
56 - *
57 - * To create a new type of `ReactClass`, pass a specification of
58 - * your new class to `React.createClass`. The only requirement of your class
59 - * specification is that you implement a `render` method.
60 - *
61 - * var MyComponent = React.createClass({
62 - * render: function() {
63 - * return <div>Hello World</div>;
64 - * }
65 - * });
66 - *
67 - * The class specification supports a specific protocol of methods that have
68 - * special meaning (e.g. `render`). See `ReactClassInterface` for
69 - * more the comprehensive protocol. Any other properties and methods in the
70 - * class specification will be available on the prototype.
71 - *
72 - * @interface ReactClassInterface
73 - * @internal
74 - */
75 -var ReactClassInterface: {[key: string]: SpecPolicy} = {
76 - /**
77 - * An array of Mixin objects to include when defining your component.
78 - *
79 - * @type {array}
80 - * @optional
81 - */
82 - mixins: 'DEFINE_MANY',
83 -
84 - /**
85 - * An object containing properties and methods that should be defined on
86 - * the component's constructor instead of its prototype (static methods).
87 - *
88 - * @type {object}
89 - * @optional
90 - */
91 - statics: 'DEFINE_MANY',
92 -
93 - /**
94 - * Definition of prop types for this component.
95 - *
96 - * @type {object}
97 - * @optional
98 - */
99 - propTypes: 'DEFINE_MANY',
100 -
101 - /**
102 - * Definition of context types for this component.
103 - *
104 - * @type {object}
105 - * @optional
106 - */
107 - contextTypes: 'DEFINE_MANY',
108 -
109 - /**
110 - * Definition of context types this component sets for its children.
111 - *
112 - * @type {object}
113 - * @optional
114 - */
115 - childContextTypes: 'DEFINE_MANY',
116 -
117 - // ==== Definition methods ====
118 -
119 - /**
120 - * Invoked when the component is mounted. Values in the mapping will be set on
121 - * `this.props` if that prop is not specified (i.e. using an `in` check).
122 - *
123 - * This method is invoked before `getInitialState` and therefore cannot rely
124 - * on `this.state` or use `this.setState`.
125 - *
126 - * @return {object}
127 - * @optional
128 - */
129 - getDefaultProps: 'DEFINE_MANY_MERGED',
130 -
131 - /**
132 - * Invoked once before the component is mounted. The return value will be used
133 - * as the initial value of `this.state`.
134 - *
135 - * getInitialState: function() {
136 - * return {
137 - * isOn: false,
138 - * fooBaz: new BazFoo()
139 - * }
140 - * }
141 - *
142 - * @return {object}
143 - * @optional
144 - */
145 - getInitialState: 'DEFINE_MANY_MERGED',
146 -
147 - /**
148 - * @return {object}
149 - * @optional
150 - */
151 - getChildContext: 'DEFINE_MANY_MERGED',
152 -
153 - /**
154 - * Uses props from `this.props` and state from `this.state` to render the
155 - * structure of the component.
156 - *
157 - * No guarantees are made about when or how often this method is invoked, so
158 - * it must not have side effects.
159 - *
160 - * render: function() {
161 - * var name = this.props.name;
162 - * return <div>Hello, {name}!</div>;
163 - * }
164 - *
165 - * @return {ReactComponent}
166 - * @required
167 - */
168 - render: 'DEFINE_ONCE',
169 -
170 - // ==== Delegate methods ====
171 -
172 - /**
173 - * Invoked when the component is initially created and about to be mounted.
174 - * This may have side effects, but any external subscriptions or data created
175 - * by this method must be cleaned up in `componentWillUnmount`.
176 - *
177 - * @optional
178 - */
179 - componentWillMount: 'DEFINE_MANY',
180 -
181 - /**
182 - * Invoked when the component has been mounted and has a DOM representation.
183 - * However, there is no guarantee that the DOM node is in the document.
184 - *
185 - * Use this as an opportunity to operate on the DOM when the component has
186 - * been mounted (initialized and rendered) for the first time.
187 - *
188 - * @param {DOMElement} rootNode DOM element representing the component.
189 - * @optional
190 - */
191 - componentDidMount: 'DEFINE_MANY',
192 -
193 - /**
194 - * Invoked before the component receives new props.
195 - *
196 - * Use this as an opportunity to react to a prop transition by updating the
197 - * state using `this.setState`. Current props are accessed via `this.props`.
198 - *
199 - * componentWillReceiveProps: function(nextProps, nextContext) {
200 - * this.setState({
201 - * likesIncreasing: nextProps.likeCount > this.props.likeCount
202 - * });
203 - * }
204 - *
205 - * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
206 - * transition may cause a state change, but the opposite is not true. If you
207 - * need it, you are probably looking for `componentWillUpdate`.
208 - *
209 - * @param {object} nextProps
210 - * @optional
211 - */
212 - componentWillReceiveProps: 'DEFINE_MANY',
213 -
214 - /**
215 - * Invoked while deciding if the component should be updated as a result of
216 - * receiving new props, state and/or context.
217 - *
218 - * Use this as an opportunity to `return false` when you're certain that the
219 - * transition to the new props/state/context will not require a component
220 - * update.
221 - *
222 - * shouldComponentUpdate: function(nextProps, nextState, nextContext) {
223 - * return !equal(nextProps, this.props) ||
224 - * !equal(nextState, this.state) ||
225 - * !equal(nextContext, this.context);
226 - * }
227 - *
228 - * @param {object} nextProps
229 - * @param {?object} nextState
230 - * @param {?object} nextContext
231 - * @return {boolean} True if the component should update.
232 - * @optional
233 - */
234 - shouldComponentUpdate: 'DEFINE_ONCE',
235 -
236 - /**
237 - * Invoked when the component is about to update due to a transition from
238 - * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
239 - * and `nextContext`.
240 - *
241 - * Use this as an opportunity to perform preparation before an update occurs.
242 - *
243 - * NOTE: You **cannot** use `this.setState()` in this method.
244 - *
245 - * @param {object} nextProps
246 - * @param {?object} nextState
247 - * @param {?object} nextContext
248 - * @param {ReactReconcileTransaction} transaction
249 - * @optional
250 - */
251 - componentWillUpdate: 'DEFINE_MANY',
252 -
253 - /**
254 - * Invoked when the component's DOM representation has been updated.
255 - *
256 - * Use this as an opportunity to operate on the DOM when the component has
257 - * been updated.
258 - *
259 - * @param {object} prevProps
260 - * @param {?object} prevState
261 - * @param {?object} prevContext
262 - * @param {DOMElement} rootNode DOM element representing the component.
263 - * @optional
264 - */
265 - componentDidUpdate: 'DEFINE_MANY',
266 -
267 - /**
268 - * Invoked when the component is about to be removed from its parent and have
269 - * its DOM representation destroyed.
270 - *
271 - * Use this as an opportunity to deallocate any external resources.
272 - *
273 - * NOTE: There is no `componentDidUnmount` since your component will have been
274 - * destroyed by that point.
275 - *
276 - * @optional
277 - */
278 - componentWillUnmount: 'DEFINE_MANY',
279 -
280 - // ==== Advanced methods ====
281 -
282 - /**
283 - * Updates the component's currently mounted DOM representation.
284 - *
285 - * By default, this implements React's rendering and reconciliation algorithm.
286 - * Sophisticated clients may wish to override this.
287 - *
288 - * @param {ReactReconcileTransaction} transaction
289 - * @internal
290 - * @overridable
291 - */
292 - updateComponent: 'OVERRIDE_BASE',
293 -};
294 -
295 -/**
296 - * Mapping from class specification keys to special processing functions.
297 - *
298 - * Although these are declared like instance properties in the specification
299 - * when defining classes using `React.createClass`, they are actually static
300 - * and are accessible on the constructor instead of the prototype. Despite
301 - * being static, they must be defined outside of the "statics" key under
302 - * which all other static methods are defined.
303 - */
304 -var RESERVED_SPEC_KEYS = {
305 - displayName: function(Constructor, displayName) {
306 - Constructor.displayName = displayName;
307 - },
308 - mixins: function(Constructor, mixins) {
309 - if (mixins) {
310 - for (var i = 0; i < mixins.length; i++) {
311 - mixSpecIntoComponent(Constructor, mixins[i]);
312 - }
313 - }
314 - },
315 - childContextTypes: function(Constructor, childContextTypes) {
316 - if (__DEV__) {
317 - validateTypeDef(Constructor, childContextTypes, 'child context');
318 - }
319 - Constructor.childContextTypes = Object.assign(
320 - {},
321 - Constructor.childContextTypes,
322 - childContextTypes,
323 - );
324 - },
325 - contextTypes: function(Constructor, contextTypes) {
326 - if (__DEV__) {
327 - validateTypeDef(Constructor, contextTypes, 'context');
328 - }
329 - Constructor.contextTypes = Object.assign(
330 - {},
331 - Constructor.contextTypes,
332 - contextTypes,
333 - );
334 - },
335 - /**
336 - * Special case getDefaultProps which should move into statics but requires
337 - * automatic merging.
338 - */
339 - getDefaultProps: function(Constructor, getDefaultProps) {
340 - if (Constructor.getDefaultProps) {
341 - Constructor.getDefaultProps = createMergedResultFunction(
342 - Constructor.getDefaultProps,
343 - getDefaultProps,
344 - );
345 - } else {
346 - Constructor.getDefaultProps = getDefaultProps;
347 - }
348 - },
349 - propTypes: function(Constructor, propTypes) {
350 - if (__DEV__) {
351 - validateTypeDef(Constructor, propTypes, 'prop');
352 - }
353 - Constructor.propTypes = Object.assign({}, Constructor.propTypes, propTypes);
354 - },
355 - statics: function(Constructor, statics) {
356 - mixStaticSpecIntoComponent(Constructor, statics);
357 - },
358 - autobind: function() {}, // noop
359 -};
360 -
361 -function validateTypeDef(Constructor, typeDef, location: string) {
362 - for (var propName in typeDef) {
363 - if (typeDef.hasOwnProperty(propName)) {
364 - // use a warning instead of an invariant so components
365 - // don't show up in prod but only in __DEV__
366 - warning(
367 - typeof typeDef[propName] === 'function',
368 - '%s: %s type `%s` is invalid; it must be a function, usually from ' +
369 - 'React.PropTypes.',
370 - Constructor.displayName || 'ReactClass',
371 - location,
372 - propName,
373 - );
374 - }
375 - }
376 -}
377 -
378 -function validateMethodOverride(isAlreadyDefined, name) {
379 - var specPolicy = ReactClassInterface.hasOwnProperty(name)
380 - ? ReactClassInterface[name]
381 - : null;
382 -
383 - // Disallow overriding of base class methods unless explicitly allowed.
384 - if (ReactClassMixin.hasOwnProperty(name)) {
385 - invariant(
386 - specPolicy === 'OVERRIDE_BASE',
387 - 'ReactClassInterface: You are attempting to override ' +
388 - '`%s` from your class specification. Ensure that your method names ' +
389 - 'do not overlap with React methods.',
390 - name,
391 - );
392 - }
393 -
394 - // Disallow defining methods more than once unless explicitly allowed.
395 - if (isAlreadyDefined) {
396 - invariant(
397 - specPolicy === 'DEFINE_MANY' || specPolicy === 'DEFINE_MANY_MERGED',
398 - 'ReactClassInterface: You are attempting to define ' +
399 - '`%s` on your component more than once. This conflict may be due ' +
400 - 'to a mixin.',
401 - name,
402 - );
403 - }
404 -}
405 -
406 -/**
407 - * Mixin helper which handles policy validation and reserved
408 - * specification keys when building React classes.
409 - */
410 -function mixSpecIntoComponent(Constructor, spec) {
411 - if (!spec) {
412 - if (__DEV__) {
413 - var typeofSpec = typeof spec;
414 - var isMixinValid = typeofSpec === 'object' && spec !== null;
415 -
416 - warning(
417 - isMixinValid,
418 - "%s: You're attempting to include a mixin that is either null " +
419 - 'or not an object. Check the mixins included by the component, ' +
420 - 'as well as any mixins they include themselves. ' +
421 - 'Expected object but got %s.',
422 - Constructor.displayName || 'ReactClass',
423 - spec === null ? null : typeofSpec,
424 - );
425 - }
426 -
427 - return;
428 - }
429 -
430 - invariant(
431 - typeof spec !== 'function',
432 - "ReactClass: You're attempting to " +
433 - 'use a component class or function as a mixin. Instead, just use a ' +
434 - 'regular object.',
435 - );
436 - invariant(
437 - !ReactElement.isValidElement(spec),
438 - "ReactClass: You're attempting to " +
439 - 'use a component as a mixin. Instead, just use a regular object.',
440 - );
441 -
442 - var proto = Constructor.prototype;
443 - var autoBindPairs = proto.__reactAutoBindPairs;
444 -
445 - // By handling mixins before any other properties, we ensure the same
446 - // chaining order is applied to methods with DEFINE_MANY policy, whether
447 - // mixins are listed before or after these methods in the spec.
448 - if (spec.hasOwnProperty(MIXINS_KEY)) {
449 - RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
450 - }
451 -
452 - for (var name in spec) {
453 - if (!spec.hasOwnProperty(name)) {
454 - continue;
455 - }
456 -
457 - if (name === MIXINS_KEY) {
458 - // We have already handled mixins in a special case above.
459 - continue;
460 - }
461 -
462 - var property = spec[name];
463 - var isAlreadyDefined = proto.hasOwnProperty(name);
464 - validateMethodOverride(isAlreadyDefined, name);
465 -
466 - if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
467 - RESERVED_SPEC_KEYS[name](Constructor, property);
468 - } else {
469 - // Setup methods on prototype:
470 - // The following member methods should not be automatically bound:
471 - // 1. Expected ReactClass methods (in the "interface").
472 - // 2. Overridden methods (that were mixed in).
473 - var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
474 - var isFunction = typeof property === 'function';
475 - var shouldAutoBind = isFunction &&
476 - !isReactClassMethod &&
477 - !isAlreadyDefined &&
478 - spec.autobind !== false;
479 -
480 - if (shouldAutoBind) {
481 - autoBindPairs.push(name, property);
482 - proto[name] = property;
483 - } else {
484 - if (isAlreadyDefined) {
485 - var specPolicy = ReactClassInterface[name];
486 -
487 - // These cases should already be caught by validateMethodOverride.
488 - invariant(
489 - isReactClassMethod &&
490 - (specPolicy === 'DEFINE_MANY_MERGED' ||
491 - specPolicy === 'DEFINE_MANY'),
492 - 'ReactClass: Unexpected spec policy %s for key %s ' +
493 - 'when mixing in component specs.',
494 - specPolicy,
495 - name,
496 - );
497 -
498 - // For methods which are defined more than once, call the existing
499 - // methods before calling the new property, merging if appropriate.
500 - if (specPolicy === 'DEFINE_MANY_MERGED') {
501 - proto[name] = createMergedResultFunction(proto[name], property);
502 - } else if (specPolicy === 'DEFINE_MANY') {
503 - proto[name] = createChainedFunction(proto[name], property);
504 - }
505 - } else {
506 - proto[name] = property;
507 - if (__DEV__) {
508 - // Add verbose displayName to the function, which helps when looking
509 - // at profiling tools.
510 - if (typeof property === 'function' && spec.displayName) {
511 - proto[name].displayName = spec.displayName + '_' + name;
512 - }
513 - }
514 - }
515 - }
516 - }
517 - }
518 -}
519 -
520 -function mixStaticSpecIntoComponent(Constructor, statics) {
521 - if (!statics) {
522 - return;
523 - }
524 - for (var name in statics) {
525 - var property = statics[name];
526 - if (!statics.hasOwnProperty(name)) {
527 - continue;
528 - }
529 -
530 - var isReserved = name in RESERVED_SPEC_KEYS;
531 - invariant(
532 - !isReserved,
533 - 'ReactClass: You are attempting to define a reserved ' +
534 - 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
535 - 'as an instance property instead; it will still be accessible on the ' +
536 - 'constructor.',
537 - name,
538 - );
539 -
540 - var isInherited = name in Constructor;
541 - invariant(
542 - !isInherited,
543 - 'ReactClass: You are attempting to define ' +
544 - '`%s` on your component more than once. This conflict may be ' +
545 - 'due to a mixin.',
546 - name,
547 - );
548 - Constructor[name] = property;
549 - }
550 -}
551 -
552 -/**
553 - * Merge two objects, but throw if both contain the same key.
554 - *
555 - * @param {object} one The first object, which is mutated.
556 - * @param {object} two The second object
557 - * @return {object} one after it has been mutated to contain everything in two.
558 - */
559 -function mergeIntoWithNoDuplicateKeys(one, two) {
560 - invariant(
561 - one && two && typeof one === 'object' && typeof two === 'object',
562 - 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.',
563 - );
564 -
565 - for (var key in two) {
566 - if (two.hasOwnProperty(key)) {
567 - invariant(
568 - one[key] === undefined,
569 - 'mergeIntoWithNoDuplicateKeys(): ' +
570 - 'Tried to merge two objects with the same key: `%s`. This conflict ' +
571 - 'may be due to a mixin; in particular, this may be caused by two ' +
572 - 'getInitialState() or getDefaultProps() methods returning objects ' +
573 - 'with clashing keys.',
574 - key,
575 - );
576 - one[key] = two[key];
577 - }
578 - }
579 - return one;
580 -}
581 -
582 -/**
583 - * Creates a function that invokes two functions and merges their return values.
584 - *
585 - * @param {function} one Function to invoke first.
586 - * @param {function} two Function to invoke second.
587 - * @return {function} Function that invokes the two argument functions.
588 - * @private
589 - */
590 -function createMergedResultFunction(one, two) {
591 - return function mergedResult() {
592 - var a = one.apply(this, arguments);
593 - var b = two.apply(this, arguments);
594 - if (a == null) {
595 - return b;
596 - } else if (b == null) {
597 - return a;
598 - }
599 - var c = {};
600 - mergeIntoWithNoDuplicateKeys(c, a);
601 - mergeIntoWithNoDuplicateKeys(c, b);
602 - return c;
603 - };
604 -}
605 -
606 -/**
607 - * Creates a function that invokes two functions and ignores their return vales.
608 - *
609 - * @param {function} one Function to invoke first.
610 - * @param {function} two Function to invoke second.
611 - * @return {function} Function that invokes the two argument functions.
612 - * @private
613 - */
614 -function createChainedFunction(one, two) {
615 - return function chainedFunction() {
616 - one.apply(this, arguments);
617 - two.apply(this, arguments);
618 - };
619 -}
620 -
621 -/**
622 - * Binds a method to the component.
623 - *
624 - * @param {object} component Component whose method is going to be bound.
625 - * @param {function} method Method to be bound.
626 - * @return {function} The bound method.
627 - */
628 -function bindAutoBindMethod(component, method) {
629 - var boundMethod = method.bind(component);
630 - if (__DEV__) {
631 - boundMethod.__reactBoundContext = component;
632 - boundMethod.__reactBoundMethod = method;
633 - boundMethod.__reactBoundArguments = null;
634 - var componentName = component.constructor.displayName;
635 - var _bind = boundMethod.bind;
636 - boundMethod.bind = function(newThis, ...args) {
637 - // User is trying to bind() an autobound method; we effectively will
638 - // ignore the value of "this" that the user is trying to use, so
639 - // let's warn.
640 - if (newThis !== component && newThis !== null) {
641 - warning(
642 - false,
643 - 'bind(): React component methods may only be bound to the ' +
644 - 'component instance.\n\nSee %s',
645 - componentName,
646 - );
647 - } else if (!args.length) {
648 - warning(
649 - false,
650 - 'bind(): You are binding a component method to the component. ' +
651 - 'React does this for you automatically in a high-performance ' +
652 - 'way, so you can safely remove this call.\n\nSee %s',
653 - componentName,
654 - );
655 - return boundMethod;
656 - }
657 - var reboundMethod = _bind.apply(boundMethod, arguments);
658 - reboundMethod.__reactBoundContext = component;
659 - reboundMethod.__reactBoundMethod = method;
660 - reboundMethod.__reactBoundArguments = args;
661 - return reboundMethod;
662 - };
663 - }
664 - return boundMethod;
665 -}
666 -
667 -/**
668 - * Binds all auto-bound methods in a component.
669 - *
670 - * @param {object} component Component whose method is going to be bound.
671 - */
672 -function bindAutoBindMethods(component) {
673 - var pairs = component.__reactAutoBindPairs;
674 - for (var i = 0; i < pairs.length; i += 2) {
675 - var autoBindKey = pairs[i];
676 - var method = pairs[i + 1];
677 - component[autoBindKey] = bindAutoBindMethod(component, method);
678 - }
679 -}
680 -
681 -/**
682 - * Add more to the ReactClass base class. These are all legacy features and
683 - * therefore not already part of the modern ReactComponent.
684 - */
685 -var ReactClassMixin = {
686 - /**
687 - * TODO: This will be deprecated because state should always keep a consistent
688 - * type signature and the only use case for this, is to avoid that.
689 - */
690 - replaceState: function(newState, callback) {
691 - this.updater.enqueueReplaceState(this, newState, callback, 'replaceState');
692 - },
693 -
694 - /**
695 - * Checks whether or not this composite component is mounted.
696 - * @return {boolean} True if mounted, false otherwise.
697 - * @protected
698 - * @final
699 - */
700 - isMounted: function() {
701 - return this.updater.isMounted(this);
702 - },
703 -};
704 -
705 -var ReactClassComponent = function() {};
706 -Object.assign(
707 - ReactClassComponent.prototype,
708 - ReactComponent.prototype,
709 - ReactClassMixin,
710 -);
711 -
712 -/**
713 - * Module for creating composite components.
714 - *
715 - * @class ReactClass
716 - */
717 -var ReactClass = {
718 - /**
719 - * Creates a composite component class given a class specification.
720 - * See https://facebook.github.io/react/docs/react-api.html#createclass
721 - *
722 - * @param {object} spec Class specification (which must define `render`).
723 - * @return {function} Component constructor function.
724 - * @public
725 - */
726 - createClass: function(spec) {
727 - // To keep our warnings more understandable, we'll use a little hack here to
728 - // ensure that Constructor.name !== 'Constructor'. This makes sure we don't
729 - // unnecessarily identify a class without displayName as 'Constructor'.
730 - var Constructor = identity(function(props, context, updater) {
731 - // This constructor gets overridden by mocks. The argument is used
732 - // by mocks to assert on what gets mounted.
733 -
734 - if (__DEV__) {
735 - warning(
736 - this instanceof Constructor,
737 - 'Something is calling a React component directly. Use a factory or ' +
738 - 'JSX instead. See: https://fb.me/react-legacyfactory',
739 - );
740 - }
741 -
742 - // Wire up auto-binding
743 - if (this.__reactAutoBindPairs.length) {
744 - bindAutoBindMethods(this);
745 - }
746 -
747 - this.props = props;
748 - this.context = context;
749 - this.refs = emptyObject;
750 - this.updater = updater || ReactNoopUpdateQueue;
751 -
752 - this.state = null;
753 -
754 - // ReactClasses doesn't have constructors. Instead, they use the
755 - // getInitialState and componentWillMount methods for initialization.
756 -
757 - var initialState = this.getInitialState ? this.getInitialState() : null;
758 - if (__DEV__) {
759 - // We allow auto-mocks to proceed as if they're returning null.
760 - if (
761 - initialState === undefined && this.getInitialState._isMockFunction
762 - ) {
763 - // This is probably bad practice. Consider warning here and
764 - // deprecating this convenience.
765 - initialState = null;
766 - }
767 - }
768 - invariant(
769 - typeof initialState === 'object' && !Array.isArray(initialState),
770 - '%s.getInitialState(): must return an object or null',
771 - Constructor.displayName || 'ReactCompositeComponent',
772 - );
773 -
774 - this.state = initialState;
775 - });
776 - Constructor.prototype = new ReactClassComponent();
777 - Constructor.prototype.constructor = Constructor;
778 - Constructor.prototype.__reactAutoBindPairs = [];
779 -
780 - mixSpecIntoComponent(Constructor, spec);
781 -
782 - // Initialize the defaultProps property after all mixins have been merged.
783 - if (Constructor.getDefaultProps) {
784 - Constructor.defaultProps = Constructor.getDefaultProps();
785 - }
786 -
787 - if (__DEV__) {
788 - // This is a tag to indicate that the use of these method names is ok,
789 - // since it's used with createClass. If it's not, then it's likely a
790 - // mistake so we'll warn you to use the static property, property
791 - // initializer or constructor respectively.
792 - if (Constructor.getDefaultProps) {
793 - Constructor.getDefaultProps.isReactClassApproved = {};
794 - }
795 - if (Constructor.prototype.getInitialState) {
796 - Constructor.prototype.getInitialState.isReactClassApproved = {};
797 - }
798 - }
799 -
800 - invariant(
801 - Constructor.prototype.render,
802 - 'createClass(...): Class specification must implement a `render` method.',
803 - );
804 -
805 - if (__DEV__) {
806 - warning(
807 - !Constructor.prototype.componentShouldUpdate,
808 - '%s has a method called ' +
809 - 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
810 - 'The name is phrased as a question because the function is ' +
811 - 'expected to return a value.',
812 - spec.displayName || 'A component',
813 - );
814 - warning(
815 - !Constructor.prototype.componentWillRecieveProps,
816 - '%s has a method called ' +
817 - 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
818 - spec.displayName || 'A component',
819 - );
820 - }
821 -
822 - // Reduce time spent doing lookups by setting these on the prototype.
823 - for (var methodName in ReactClassInterface) {
824 - if (!Constructor.prototype[methodName]) {
825 - Constructor.prototype[methodName] = null;
826 - }
827 - }
828 -
829 - return Constructor;
830 - },
831 -};
832 -
833 -module.exports = ReactClass;
src/isomorphic/classic/class/__tests__/ReactBind-test.js deleted
-152
@@ -1,152 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @emails react-core
10 - */
11 -/*global global:true*/
12 -'use strict';
13 -
14 -var React = require('react');
15 -var ReactTestUtils = require('ReactTestUtils');
16 -
17 -// TODO: Test render and all stock methods.
18 -describe('autobinding', () => {
19 - it('Holds reference to instance', () => {
20 - var mouseDidEnter = jest.fn();
21 - var mouseDidLeave = jest.fn();
22 - var mouseDidClick = jest.fn();
23 -
24 - var TestBindComponent = React.createClass({
25 - getInitialState: function() {
26 - return {something: 'hi'};
27 - },
28 - onMouseEnter: mouseDidEnter,
29 - onMouseLeave: mouseDidLeave,
30 - onClick: mouseDidClick,
31 -
32 - // auto binding only occurs on top level functions in class defs.
33 - badIdeas: {
34 - badBind: function() {
35 - void this.state.something;
36 - },
37 - },
38 -
39 - render: function() {
40 - return (
41 - <div
42 - ref="child"
43 - onMouseOver={this.onMouseEnter}
44 - onMouseOut={this.onMouseLeave}
45 - onClick={this.onClick}
46 - />
47 - );
48 - },
49 - });
50 -
51 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
52 - var rendered1 = instance1.refs.child;
53 -
54 - var instance2 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
55 - var rendered2 = instance2.refs.child;
56 -
57 - expect(function() {
58 - var badIdea = instance1.badIdeas.badBind;
59 - badIdea();
60 - }).toThrow();
61 -
62 - expect(instance1.onClick).not.toBe(instance2.onClick);
63 -
64 - ReactTestUtils.Simulate.click(rendered1);
65 - expect(mouseDidClick.mock.instances.length).toBe(1);
66 - expect(mouseDidClick.mock.instances[0]).toBe(instance1);
67 -
68 - ReactTestUtils.Simulate.click(rendered2);
69 - expect(mouseDidClick.mock.instances.length).toBe(2);
70 - expect(mouseDidClick.mock.instances[1]).toBe(instance2);
71 -
72 - ReactTestUtils.Simulate.mouseOver(rendered1);
73 - expect(mouseDidEnter.mock.instances.length).toBe(1);
74 - expect(mouseDidEnter.mock.instances[0]).toBe(instance1);
75 -
76 - ReactTestUtils.Simulate.mouseOver(rendered2);
77 - expect(mouseDidEnter.mock.instances.length).toBe(2);
78 - expect(mouseDidEnter.mock.instances[1]).toBe(instance2);
79 -
80 - ReactTestUtils.Simulate.mouseOut(rendered1);
81 - expect(mouseDidLeave.mock.instances.length).toBe(1);
82 - expect(mouseDidLeave.mock.instances[0]).toBe(instance1);
83 -
84 - ReactTestUtils.Simulate.mouseOut(rendered2);
85 - expect(mouseDidLeave.mock.instances.length).toBe(2);
86 - expect(mouseDidLeave.mock.instances[1]).toBe(instance2);
87 - });
88 -
89 - it('works with mixins', () => {
90 - var mouseDidClick = jest.fn();
91 -
92 - var TestMixin = {
93 - onClick: mouseDidClick,
94 - };
95 -
96 - var TestBindComponent = React.createClass({
97 - mixins: [TestMixin],
98 -
99 - render: function() {
100 - return <div ref="child" onClick={this.onClick} />;
101 - },
102 - });
103 -
104 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
105 - var rendered1 = instance1.refs.child;
106 -
107 - ReactTestUtils.Simulate.click(rendered1);
108 - expect(mouseDidClick.mock.instances.length).toBe(1);
109 - expect(mouseDidClick.mock.instances[0]).toBe(instance1);
110 - });
111 -
112 - it('warns if you try to bind to this', () => {
113 - spyOn(console, 'error');
114 -
115 - var TestBindComponent = React.createClass({
116 - handleClick: function() {},
117 - render: function() {
118 - return <div onClick={this.handleClick.bind(this)} />;
119 - },
120 - });
121 -
122 - ReactTestUtils.renderIntoDocument(<TestBindComponent />);
123 -
124 - expectDev(console.error.calls.count()).toBe(1);
125 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
126 - 'Warning: bind(): You are binding a component method to the component. ' +
127 - 'React does this for you automatically in a high-performance ' +
128 - 'way, so you can safely remove this call.\n\nSee TestBindComponent',
129 - );
130 - });
131 -
132 - it('does not warn if you pass an auto-bound method to setState', () => {
133 - spyOn(console, 'error');
134 -
135 - var TestBindComponent = React.createClass({
136 - getInitialState: function() {
137 - return {foo: 1};
138 - },
139 - componentDidMount: function() {
140 - this.setState({foo: 2}, this.handleUpdate);
141 - },
142 - handleUpdate: function() {},
143 - render: function() {
144 - return <div onClick={this.handleClick} />;
145 - },
146 - });
147 -
148 - ReactTestUtils.renderIntoDocument(<TestBindComponent />);
149 -
150 - expectDev(console.error.calls.count()).toBe(0);
151 - });
152 -});
src/isomorphic/classic/class/__tests__/ReactBindOptout-test.js deleted
-206
@@ -1,206 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @emails react-core
10 - */
11 -/*global global:true*/
12 -'use strict';
13 -
14 -var React = require('react');
15 -var ReactTestUtils = require('ReactTestUtils');
16 -
17 -// TODO: Test render and all stock methods.
18 -describe('autobind optout', () => {
19 - it('should work with manual binding', () => {
20 - var mouseDidEnter = jest.fn();
21 - var mouseDidLeave = jest.fn();
22 - var mouseDidClick = jest.fn();
23 -
24 - var TestBindComponent = React.createClass({
25 - autobind: false,
26 - getInitialState: function() {
27 - return {something: 'hi'};
28 - },
29 - onMouseEnter: mouseDidEnter,
30 - onMouseLeave: mouseDidLeave,
31 - onClick: mouseDidClick,
32 -
33 - render: function() {
34 - return (
35 - <div
36 - ref="child"
37 - onMouseOver={this.onMouseEnter.bind(this)}
38 - onMouseOut={this.onMouseLeave.bind(this)}
39 - onClick={this.onClick.bind(this)}
40 - />
41 - );
42 - },
43 - });
44 -
45 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
46 - var rendered1 = instance1.refs.child;
47 -
48 - var instance2 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
49 - var rendered2 = instance2.refs.child;
50 -
51 - ReactTestUtils.Simulate.click(rendered1);
52 - expect(mouseDidClick.mock.instances.length).toBe(1);
53 - expect(mouseDidClick.mock.instances[0]).toBe(instance1);
54 -
55 - ReactTestUtils.Simulate.click(rendered2);
56 - expect(mouseDidClick.mock.instances.length).toBe(2);
57 - expect(mouseDidClick.mock.instances[1]).toBe(instance2);
58 -
59 - ReactTestUtils.Simulate.mouseOver(rendered1);
60 - expect(mouseDidEnter.mock.instances.length).toBe(1);
61 - expect(mouseDidEnter.mock.instances[0]).toBe(instance1);
62 -
63 - ReactTestUtils.Simulate.mouseOver(rendered2);
64 - expect(mouseDidEnter.mock.instances.length).toBe(2);
65 - expect(mouseDidEnter.mock.instances[1]).toBe(instance2);
66 -
67 - ReactTestUtils.Simulate.mouseOut(rendered1);
68 - expect(mouseDidLeave.mock.instances.length).toBe(1);
69 - expect(mouseDidLeave.mock.instances[0]).toBe(instance1);
70 -
71 - ReactTestUtils.Simulate.mouseOut(rendered2);
72 - expect(mouseDidLeave.mock.instances.length).toBe(2);
73 - expect(mouseDidLeave.mock.instances[1]).toBe(instance2);
74 - });
75 -
76 - it('should not hold reference to instance', () => {
77 - var mouseDidClick = function() {
78 - void this.state.something;
79 - };
80 -
81 - var TestBindComponent = React.createClass({
82 - autobind: false,
83 - getInitialState: function() {
84 - return {something: 'hi'};
85 - },
86 - onClick: mouseDidClick,
87 -
88 - // auto binding only occurs on top level functions in class defs.
89 - badIdeas: {
90 - badBind: function() {
91 - void this.state.something;
92 - },
93 - },
94 -
95 - render: function() {
96 - return <div ref="child" onClick={this.onClick} />;
97 - },
98 - });
99 -
100 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
101 - var rendered1 = instance1.refs.child;
102 -
103 - var instance2 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
104 - var rendered2 = instance2.refs.child;
105 -
106 - expect(function() {
107 - var badIdea = instance1.badIdeas.badBind;
108 - badIdea();
109 - }).toThrow();
110 -
111 - expect(instance1.onClick).toBe(instance2.onClick);
112 -
113 - expect(function() {
114 - ReactTestUtils.Simulate.click(rendered1);
115 - }).toThrow();
116 -
117 - expect(function() {
118 - ReactTestUtils.Simulate.click(rendered2);
119 - }).toThrow();
120 - });
121 -
122 - it('works with mixins that have not opted out of autobinding', () => {
123 - var mouseDidClick = jest.fn();
124 -
125 - var TestMixin = {
126 - onClick: mouseDidClick,
127 - };
128 -
129 - var TestBindComponent = React.createClass({
130 - mixins: [TestMixin],
131 -
132 - render: function() {
133 - return <div ref="child" onClick={this.onClick} />;
134 - },
135 - });
136 -
137 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
138 - var rendered1 = instance1.refs.child;
139 -
140 - ReactTestUtils.Simulate.click(rendered1);
141 - expect(mouseDidClick.mock.instances.length).toBe(1);
142 - expect(mouseDidClick.mock.instances[0]).toBe(instance1);
143 - });
144 -
145 - it('works with mixins that have opted out of autobinding', () => {
146 - var mouseDidClick = jest.fn();
147 -
148 - var TestMixin = {
149 - autobind: false,
150 - onClick: mouseDidClick,
151 - };
152 -
153 - var TestBindComponent = React.createClass({
154 - mixins: [TestMixin],
155 -
156 - render: function() {
157 - return <div ref="child" onClick={this.onClick.bind(this)} />;
158 - },
159 - });
160 -
161 - var instance1 = ReactTestUtils.renderIntoDocument(<TestBindComponent />);
162 - var rendered1 = instance1.refs.child;
163 -
164 - ReactTestUtils.Simulate.click(rendered1);
165 - expect(mouseDidClick.mock.instances.length).toBe(1);
166 - expect(mouseDidClick.mock.instances[0]).toBe(instance1);
167 - });
168 -
169 - it('does not warn if you try to bind to this', () => {
170 - spyOn(console, 'error');
171 -
172 - var TestBindComponent = React.createClass({
173 - autobind: false,
174 - handleClick: function() {},
175 - render: function() {
176 - return <div onClick={this.handleClick.bind(this)} />;
177 - },
178 - });
179 -
180 - ReactTestUtils.renderIntoDocument(<TestBindComponent />);
181 -
182 - expectDev(console.error.calls.count()).toBe(0);
183 - });
184 -
185 - it('does not warn if you pass an manually bound method to setState', () => {
186 - spyOn(console, 'error');
187 -
188 - var TestBindComponent = React.createClass({
189 - autobind: false,
190 - getInitialState: function() {
191 - return {foo: 1};
192 - },
193 - componentDidMount: function() {
194 - this.setState({foo: 2}, this.handleUpdate.bind(this));
195 - },
196 - handleUpdate: function() {},
197 - render: function() {
198 - return <div />;
199 - },
200 - });
201 -
202 - ReactTestUtils.renderIntoDocument(<TestBindComponent />);
203 -
204 - expectDev(console.error.calls.count()).toBe(0);
205 - });
206 -});
src/isomorphic/classic/class/__tests__/ReactClass-test.js deleted
-348
@@ -1,348 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @emails react-core
10 - */
11 -
12 -'use strict';
13 -
14 -var React;
15 -var ReactDOM;
16 -var ReactTestUtils;
17 -
18 -describe('ReactClass-spec', () => {
19 - beforeEach(() => {
20 - React = require('react');
21 - ReactDOM = require('react-dom');
22 - ReactTestUtils = require('ReactTestUtils');
23 - });
24 -
25 - it('should throw when `render` is not specified', () => {
26 - expect(function() {
27 - React.createClass({});
28 - }).toThrowError(
29 - 'createClass(...): Class specification must implement a `render` method.',
30 - );
31 - });
32 -
33 - it('should copy `displayName` onto the Constructor', () => {
34 - var TestComponent = React.createClass({
35 - render: function() {
36 - return <div />;
37 - },
38 - });
39 -
40 - expect(TestComponent.displayName).toBe('TestComponent');
41 - });
42 -
43 - it('should copy prop types onto the Constructor', () => {
44 - var propValidator = jest.fn();
45 - var TestComponent = React.createClass({
46 - propTypes: {
47 - value: propValidator,
48 - },
49 - render: function() {
50 - return <div />;
51 - },
52 - });
53 -
54 - expect(TestComponent.propTypes).toBeDefined();
55 - expect(TestComponent.propTypes.value).toBe(propValidator);
56 - });
57 -
58 - it('should warn on invalid prop types', () => {
59 - spyOn(console, 'error');
60 - React.createClass({
61 - displayName: 'Component',
62 - propTypes: {
63 - prop: null,
64 - },
65 - render: function() {
66 - return <span>{this.props.prop}</span>;
67 - },
68 - });
69 - expectDev(console.error.calls.count()).toBe(1);
70 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
71 - 'Warning: Component: prop type `prop` is invalid; ' +
72 - 'it must be a function, usually from React.PropTypes.',
73 - );
74 - });
75 -
76 - it('should warn on invalid context types', () => {
77 - spyOn(console, 'error');
78 - React.createClass({
79 - displayName: 'Component',
80 - contextTypes: {
81 - prop: null,
82 - },
83 - render: function() {
84 - return <span>{this.props.prop}</span>;
85 - },
86 - });
87 - expectDev(console.error.calls.count()).toBe(1);
88 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
89 - 'Warning: Component: context type `prop` is invalid; ' +
90 - 'it must be a function, usually from React.PropTypes.',
91 - );
92 - });
93 -
94 - it('should throw on invalid child context types', () => {
95 - spyOn(console, 'error');
96 - React.createClass({
97 - displayName: 'Component',
98 - childContextTypes: {
99 - prop: null,
100 - },
101 - render: function() {
102 - return <span>{this.props.prop}</span>;
103 - },
104 - });
105 - expectDev(console.error.calls.count()).toBe(1);
106 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
107 - 'Warning: Component: child context type `prop` is invalid; ' +
108 - 'it must be a function, usually from React.PropTypes.',
109 - );
110 - });
111 -
112 - it('should warn when mispelling shouldComponentUpdate', () => {
113 - spyOn(console, 'error');
114 -
115 - React.createClass({
116 - componentShouldUpdate: function() {
117 - return false;
118 - },
119 - render: function() {
120 - return <div />;
121 - },
122 - });
123 - expectDev(console.error.calls.count()).toBe(1);
124 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
125 - 'Warning: A component has a method called componentShouldUpdate(). Did you ' +
126 - 'mean shouldComponentUpdate()? The name is phrased as a question ' +
127 - 'because the function is expected to return a value.',
128 - );
129 -
130 - React.createClass({
131 - displayName: 'NamedComponent',
132 - componentShouldUpdate: function() {
133 - return false;
134 - },
135 - render: function() {
136 - return <div />;
137 - },
138 - });
139 - expectDev(console.error.calls.count()).toBe(2);
140 - expectDev(console.error.calls.argsFor(1)[0]).toBe(
141 - 'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
142 - 'mean shouldComponentUpdate()? The name is phrased as a question ' +
143 - 'because the function is expected to return a value.',
144 - );
145 - });
146 -
147 - it('should warn when mispelling componentWillReceiveProps', () => {
148 - spyOn(console, 'error');
149 - React.createClass({
150 - componentWillRecieveProps: function() {
151 - return false;
152 - },
153 - render: function() {
154 - return <div />;
155 - },
156 - });
157 - expectDev(console.error.calls.count()).toBe(1);
158 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
159 - 'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
160 - 'mean componentWillReceiveProps()?',
161 - );
162 - });
163 -
164 - it('should throw if a reserved property is in statics', () => {
165 - expect(function() {
166 - React.createClass({
167 - statics: {
168 - getDefaultProps: function() {
169 - return {
170 - foo: 0,
171 - };
172 - },
173 - },
174 -
175 - render: function() {
176 - return <span />;
177 - },
178 - });
179 - }).toThrowError(
180 - 'ReactClass: You are attempting to define a reserved property, ' +
181 - '`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
182 - 'it as an instance property instead; it will still be accessible on ' +
183 - 'the constructor.',
184 - );
185 - });
186 -
187 - // TODO: Consider actually moving these to statics or drop this unit test.
188 -
189 - xit('should warn when using deprecated non-static spec keys', () => {
190 - spyOn(console, 'error');
191 - React.createClass({
192 - mixins: [{}],
193 - propTypes: {
194 - foo: React.PropTypes.string,
195 - },
196 - contextTypes: {
197 - foo: React.PropTypes.string,
198 - },
199 - childContextTypes: {
200 - foo: React.PropTypes.string,
201 - },
202 - render: function() {
203 - return <div />;
204 - },
205 - });
206 - expectDev(console.error.calls.count()).toBe(4);
207 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
208 - 'createClass(...): `mixins` is now a static property and should ' +
209 - 'be defined inside "statics".',
210 - );
211 - expectDev(console.error.calls.argsFor(1)[0]).toBe(
212 - 'createClass(...): `propTypes` is now a static property and should ' +
213 - 'be defined inside "statics".',
214 - );
215 - expectDev(console.error.calls.argsFor(2)[0]).toBe(
216 - 'createClass(...): `contextTypes` is now a static property and ' +
217 - 'should be defined inside "statics".',
218 - );
219 - expectDev(console.error.calls.argsFor(3)[0]).toBe(
220 - 'createClass(...): `childContextTypes` is now a static property and ' +
221 - 'should be defined inside "statics".',
222 - );
223 - });
224 -
225 - it('should support statics', () => {
226 - var Component = React.createClass({
227 - statics: {
228 - abc: 'def',
229 - def: 0,
230 - ghi: null,
231 - jkl: 'mno',
232 - pqr: function() {
233 - return this;
234 - },
235 - },
236 -
237 - render: function() {
238 - return <span />;
239 - },
240 - });
241 - var instance = <Component />;
242 - instance = ReactTestUtils.renderIntoDocument(instance);
243 - expect(instance.constructor.abc).toBe('def');
244 - expect(Component.abc).toBe('def');
245 - expect(instance.constructor.def).toBe(0);
246 - expect(Component.def).toBe(0);
247 - expect(instance.constructor.ghi).toBe(null);
248 - expect(Component.ghi).toBe(null);
249 - expect(instance.constructor.jkl).toBe('mno');
250 - expect(Component.jkl).toBe('mno');
251 - expect(instance.constructor.pqr()).toBe(Component);
252 - expect(Component.pqr()).toBe(Component);
253 - });
254 -
255 - it('should work with object getInitialState() return values', () => {
256 - var Component = React.createClass({
257 - getInitialState: function() {
258 - return {
259 - occupation: 'clown',
260 - };
261 - },
262 - render: function() {
263 - return <span />;
264 - },
265 - });
266 - var instance = <Component />;
267 - instance = ReactTestUtils.renderIntoDocument(instance);
268 - expect(instance.state.occupation).toEqual('clown');
269 - });
270 -
271 - it('renders based on context getInitialState', () => {
272 - var Foo = React.createClass({
273 - contextTypes: {
274 - className: React.PropTypes.string,
275 - },
276 - getInitialState() {
277 - return {className: this.context.className};
278 - },
279 - render() {
280 - return <span className={this.state.className} />;
281 - },
282 - });
283 -
284 - var Outer = React.createClass({
285 - childContextTypes: {
286 - className: React.PropTypes.string,
287 - },
288 - getChildContext() {
289 - return {className: 'foo'};
290 - },
291 - render() {
292 - return <Foo />;
293 - },
294 - });
295 -
296 - var container = document.createElement('div');
297 - ReactDOM.render(<Outer />, container);
298 - expect(container.firstChild.className).toBe('foo');
299 - });
300 -
301 - it('should throw with non-object getInitialState() return values', () => {
302 - [['an array'], 'a string', 1234].forEach(function(state) {
303 - var Component = React.createClass({
304 - getInitialState: function() {
305 - return state;
306 - },
307 - render: function() {
308 - return <span />;
309 - },
310 - });
311 - var instance = <Component />;
312 - expect(function() {
313 - instance = ReactTestUtils.renderIntoDocument(instance);
314 - }).toThrowError(
315 - 'Component.getInitialState(): must return an object or null',
316 - );
317 - });
318 - });
319 -
320 - it('should work with a null getInitialState() return value', () => {
321 - var Component = React.createClass({
322 - getInitialState: function() {
323 - return null;
324 - },
325 - render: function() {
326 - return <span />;
327 - },
328 - });
329 - expect(() =>
330 - ReactTestUtils.renderIntoDocument(<Component />)).not.toThrow();
331 - });
332 -
333 - it('should throw when using legacy factories', () => {
334 - spyOn(console, 'error');
335 - var Component = React.createClass({
336 - render() {
337 - return <div />;
338 - },
339 - });
340 -
341 - expect(() => Component()).toThrow();
342 - expectDev(console.error.calls.count()).toBe(1);
343 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
344 - 'Warning: Something is calling a React component directly. Use a ' +
345 - 'factory or JSX instead. See: https://fb.me/react-legacyfactory',
346 - );
347 - });
348 -});
src/isomorphic/classic/class/__tests__/ReactClassMixin-test.js deleted
-532
@@ -1,532 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @emails react-core
10 - */
11 -
12 -'use strict';
13 -
14 -var React;
15 -var ReactTestUtils;
16 -
17 -var TestComponent;
18 -var TestComponentWithPropTypes;
19 -var TestComponentWithReverseSpec;
20 -var mixinPropValidator;
21 -var componentPropValidator;
22 -
23 -describe('ReactClass-mixin', () => {
24 - beforeEach(() => {
25 - React = require('react');
26 - ReactTestUtils = require('ReactTestUtils');
27 - mixinPropValidator = jest.fn();
28 - componentPropValidator = jest.fn();
29 -
30 - var MixinA = {
31 - propTypes: {
32 - propA: function() {},
33 - },
34 - componentDidMount: function() {
35 - this.props.listener('MixinA didMount');
36 - },
37 - };
38 -
39 - var MixinB = {
40 - mixins: [MixinA],
41 - propTypes: {
42 - propB: function() {},
43 - },
44 - componentDidMount: function() {
45 - this.props.listener('MixinB didMount');
46 - },
47 - };
48 -
49 - var MixinBWithReverseSpec = {
50 - componentDidMount: function() {
51 - this.props.listener('MixinBWithReverseSpec didMount');
52 - },
53 - mixins: [MixinA],
54 - };
55 -
56 - var MixinC = {
57 - statics: {
58 - staticC: function() {},
59 - },
60 - componentDidMount: function() {
61 - this.props.listener('MixinC didMount');
62 - },
63 - };
64 -
65 - var MixinD = {
66 - propTypes: {
67 - value: mixinPropValidator,
68 - },
69 - };
70 -
71 - TestComponent = React.createClass({
72 - mixins: [MixinB, MixinC, MixinD],
73 - statics: {
74 - staticComponent: function() {},
75 - },
76 - propTypes: {
77 - propComponent: function() {},
78 - },
79 - componentDidMount: function() {
80 - this.props.listener('Component didMount');
81 - },
82 - render: function() {
83 - return <div />;
84 - },
85 - });
86 -
87 - TestComponentWithReverseSpec = React.createClass({
88 - render: function() {
89 - return <div />;
90 - },
91 - componentDidMount: function() {
92 - this.props.listener('Component didMount');
93 - },
94 - mixins: [MixinBWithReverseSpec, MixinC, MixinD],
95 - });
96 -
97 - TestComponentWithPropTypes = React.createClass({
98 - mixins: [MixinD],
99 - propTypes: {
100 - value: componentPropValidator,
101 - },
102 - render: function() {
103 - return <div />;
104 - },
105 - });
106 - });
107 -
108 - it('should support merging propTypes and statics', () => {
109 - var listener = jest.fn();
110 - var instance = <TestComponent listener={listener} />;
111 - instance = ReactTestUtils.renderIntoDocument(instance);
112 -
113 - var instancePropTypes = instance.constructor.propTypes;
114 -
115 - expect('propA' in instancePropTypes).toBe(true);
116 - expect('propB' in instancePropTypes).toBe(true);
117 - expect('propComponent' in instancePropTypes).toBe(true);
118 -
119 - expect('staticC' in TestComponent).toBe(true);
120 - expect('staticComponent' in TestComponent).toBe(true);
121 - });
122 -
123 - it('should support chaining delegate functions', () => {
124 - var listener = jest.fn();
125 - var instance = <TestComponent listener={listener} />;
126 - ReactTestUtils.renderIntoDocument(instance);
127 -
128 - expect(listener.mock.calls).toEqual([
129 - ['MixinA didMount'],
130 - ['MixinB didMount'],
131 - ['MixinC didMount'],
132 - ['Component didMount'],
133 - ]);
134 - });
135 -
136 - it('should chain functions regardless of spec property order', () => {
137 - var listener = jest.fn();
138 - var instance = <TestComponentWithReverseSpec listener={listener} />;
139 - ReactTestUtils.renderIntoDocument(instance);
140 -
141 - expect(listener.mock.calls).toEqual([
142 - ['MixinA didMount'],
143 - ['MixinBWithReverseSpec didMount'],
144 - ['MixinC didMount'],
145 - ['Component didMount'],
146 - ]);
147 - });
148 -
149 - it('should validate prop types via mixins', () => {
150 - expect(TestComponent.propTypes).toBeDefined();
151 - expect(TestComponent.propTypes.value).toBe(mixinPropValidator);
152 - });
153 -
154 - it('should override mixin prop types with class prop types', () => {
155 - // Sanity check...
156 - expect(componentPropValidator).not.toBe(mixinPropValidator);
157 - // Actually check...
158 - expect(TestComponentWithPropTypes.propTypes).toBeDefined();
159 - expect(TestComponentWithPropTypes.propTypes.value).not.toBe(
160 - mixinPropValidator,
161 - );
162 - expect(TestComponentWithPropTypes.propTypes.value).toBe(
163 - componentPropValidator,
164 - );
165 - });
166 -
167 - it('should support mixins with getInitialState()', () => {
168 - var Mixin = {
169 - getInitialState: function() {
170 - return {mixin: true};
171 - },
172 - };
173 - var Component = React.createClass({
174 - mixins: [Mixin],
175 - getInitialState: function() {
176 - return {component: true};
177 - },
178 - render: function() {
179 - return <span />;
180 - },
181 - });
182 - var instance = ReactTestUtils.renderIntoDocument(<Component />);
183 - expect(instance.state.component).toBe(true);
184 - expect(instance.state.mixin).toBe(true);
185 - });
186 -
187 - it('should throw with conflicting getInitialState() methods', () => {
188 - var Mixin = {
189 - getInitialState: function() {
190 - return {x: true};
191 - },
192 - };
193 - var Component = React.createClass({
194 - mixins: [Mixin],
195 - getInitialState: function() {
196 - return {x: true};
197 - },
198 - render: function() {
199 - return <span />;
200 - },
201 - });
202 - expect(function() {
203 - ReactTestUtils.renderIntoDocument(<Component />);
204 - }).toThrowError(
205 - 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the ' +
206 - 'same key: `x`. This conflict may be due to a mixin; in particular, ' +
207 - 'this may be caused by two getInitialState() or getDefaultProps() ' +
208 - 'methods returning objects with clashing keys.',
209 - );
210 - });
211 -
212 - it('should not mutate objects returned by getInitialState()', () => {
213 - var Mixin = {
214 - getInitialState: function() {
215 - return Object.freeze({mixin: true});
216 - },
217 - };
218 - var Component = React.createClass({
219 - mixins: [Mixin],
220 - getInitialState: function() {
221 - return Object.freeze({component: true});
222 - },
223 - render: function() {
224 - return <span />;
225 - },
226 - });
227 - expect(() => {
228 - ReactTestUtils.renderIntoDocument(<Component />);
229 - }).not.toThrow();
230 - });
231 -
232 - it('should support statics in mixins', () => {
233 - var Mixin = {
234 - statics: {
235 - foo: 'bar',
236 - },
237 - };
238 - var Component = React.createClass({
239 - mixins: [Mixin],
240 -
241 - statics: {
242 - abc: 'def',
243 - },
244 -
245 - render: function() {
246 - return <span />;
247 - },
248 - });
249 - var instance = <Component />;
250 - instance = ReactTestUtils.renderIntoDocument(instance);
251 - expect(instance.constructor.foo).toBe('bar');
252 - expect(Component.foo).toBe('bar');
253 - expect(instance.constructor.abc).toBe('def');
254 - expect(Component.abc).toBe('def');
255 - });
256 -
257 - it("should throw if mixins override each others' statics", () => {
258 - expect(function() {
259 - var Mixin = {
260 - statics: {
261 - abc: 'foo',
262 - },
263 - };
264 - React.createClass({
265 - mixins: [Mixin],
266 -
267 - statics: {
268 - abc: 'bar',
269 - },
270 -
271 - render: function() {
272 - return <span />;
273 - },
274 - });
275 - }).toThrowError(
276 - 'ReactClass: You are attempting to define `abc` on your component more ' +
277 - 'than once. This conflict may be due to a mixin.',
278 - );
279 - });
280 -
281 - it('should throw if mixins override functions in statics', () => {
282 - expect(function() {
283 - var Mixin = {
284 - statics: {
285 - abc: function() {
286 - console.log('foo');
287 - },
288 - },
289 - };
290 - React.createClass({
291 - mixins: [Mixin],
292 -
293 - statics: {
294 - abc: function() {
295 - console.log('bar');
296 - },
297 - },
298 -
299 - render: function() {
300 - return <span />;
301 - },
302 - });
303 - }).toThrowError(
304 - 'ReactClass: You are attempting to define `abc` on your component ' +
305 - 'more than once. This conflict may be due to a mixin.',
306 - );
307 - });
308 -
309 - it('should warn if the mixin is undefined', () => {
310 - spyOn(console, 'error');
311 -
312 - React.createClass({
313 - mixins: [undefined],
314 -
315 - render: function() {
316 - return <span />;
317 - },
318 - });
319 -
320 - expectDev(console.error.calls.count()).toBe(1);
321 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
322 - "Warning: ReactClass: You're attempting to include a mixin that is " +
323 - 'either null or not an object. Check the mixins included by the ' +
324 - 'component, as well as any mixins they include themselves. ' +
325 - 'Expected object but got undefined.',
326 - );
327 - });
328 -
329 - it('should warn if the mixin is null', () => {
330 - spyOn(console, 'error');
331 -
332 - React.createClass({
333 - mixins: [null],
334 -
335 - render: function() {
336 - return <span />;
337 - },
338 - });
339 -
340 - expectDev(console.error.calls.count()).toBe(1);
341 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
342 - "Warning: ReactClass: You're attempting to include a mixin that is " +
343 - 'either null or not an object. Check the mixins included by the ' +
344 - 'component, as well as any mixins they include themselves. ' +
345 - 'Expected object but got null.',
346 - );
347 - });
348 -
349 - it('should warn if an undefined mixin is included in another mixin', () => {
350 - spyOn(console, 'error');
351 -
352 - var mixinA = {
353 - mixins: [undefined],
354 - };
355 -
356 - React.createClass({
357 - mixins: [mixinA],
358 -
359 - render: function() {
360 - return <span />;
361 - },
362 - });
363 -
364 - expectDev(console.error.calls.count()).toBe(1);
365 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
366 - "Warning: ReactClass: You're attempting to include a mixin that is " +
367 - 'either null or not an object. Check the mixins included by the ' +
368 - 'component, as well as any mixins they include themselves. ' +
369 - 'Expected object but got undefined.',
370 - );
371 - });
372 -
373 - it('should warn if a null mixin is included in another mixin', () => {
374 - spyOn(console, 'error');
375 -
376 - var mixinA = {
377 - mixins: [null],
378 - };
379 -
380 - React.createClass({
381 - mixins: [mixinA],
382 -
383 - render: function() {
384 - return <span />;
385 - },
386 - });
387 -
388 - expectDev(console.error.calls.count()).toBe(1);
389 - expectDev(console.error.calls.argsFor(0)[0]).toBe(
390 - "Warning: ReactClass: You're attempting to include a mixin that is " +
391 - 'either null or not an object. Check the mixins included by the ' +
392 - 'component, as well as any mixins they include themselves. ' +
393 - 'Expected object but got null.',
394 - );
395 - });
396 -
397 - it('should throw if the mixin is a React component', () => {
398 - expect(function() {
399 - React.createClass({
400 - mixins: [<div />],
401 -
402 - render: function() {
403 - return <span />;
404 - },
405 - });
406 - }).toThrowError(
407 - "ReactClass: You're attempting to use a component as a mixin. " +
408 - 'Instead, just use a regular object.',
409 - );
410 - });
411 -
412 - it('should throw if the mixin is a React component class', () => {
413 - expect(function() {
414 - var Component = React.createClass({
415 - render: function() {
416 - return <span />;
417 - },
418 - });
419 -
420 - React.createClass({
421 - mixins: [Component],
422 -
423 - render: function() {
424 - return <span />;
425 - },
426 - });
427 - }).toThrowError(
428 - "ReactClass: You're attempting to use a component class or function " +
429 - 'as a mixin. Instead, just use a regular object.',
430 - );
431 - });
432 -
433 - it('should have bound the mixin methods to the component', () => {
434 - var mixin = {
435 - mixinFunc: function() {
436 - return this;
437 - },
438 - };
439 -
440 - var Component = React.createClass({
441 - mixins: [mixin],
442 - componentDidMount: function() {
443 - expect(this.mixinFunc()).toBe(this);
444 - },
445 - render: function() {
446 - return <span />;
447 - },
448 - });
449 - ReactTestUtils.renderIntoDocument(<Component />);
450 - });
451 -
452 - it('should include the mixin keys in even if their values are falsy', () => {
453 - var mixin = {
454 - keyWithNullValue: null,
455 - randomCounter: 0,
456 - };
457 -
458 - var Component = React.createClass({
459 - mixins: [mixin],
460 - componentDidMount: function() {
461 - expect(this.randomCounter).toBe(0);
462 - expect(this.keyWithNullValue).toBeNull();
463 - },
464 - render: function() {
465 - return <span />;
466 - },
467 - });
468 - ReactTestUtils.renderIntoDocument(<Component />);
469 - });
470 -
471 - it('should work with a null getInitialState return value and a mixin', () => {
472 - var Component;
473 - var instance;
474 -
475 - var Mixin = {
476 - getInitialState: function() {
477 - return {foo: 'bar'};
478 - },
479 - };
480 - Component = React.createClass({
481 - mixins: [Mixin],
482 - getInitialState: function() {
483 - return null;
484 - },
485 - render: function() {
486 - return <span />;
487 - },
488 - });
489 - expect(() =>
490 - ReactTestUtils.renderIntoDocument(<Component />)).not.toThrow();
491 -
492 - instance = ReactTestUtils.renderIntoDocument(<Component />);
493 - expect(instance.state).toEqual({foo: 'bar'});
494 -
495 - // Also the other way round should work
496 - var Mixin2 = {
497 - getInitialState: function() {
498 - return null;
499 - },
500 - };
501 - Component = React.createClass({
502 - mixins: [Mixin2],
503 - getInitialState: function() {
504 - return {foo: 'bar'};
505 - },
506 - render: function() {
507 - return <span />;
508 - },
509 - });
510 - expect(() =>
511 - ReactTestUtils.renderIntoDocument(<Component />)).not.toThrow();
512 -
513 - instance = ReactTestUtils.renderIntoDocument(<Component />);
514 - expect(instance.state).toEqual({foo: 'bar'});
515 -
516 - // Multiple mixins should be fine too
517 - Component = React.createClass({
518 - mixins: [Mixin, Mixin2],
519 - getInitialState: function() {
520 - return {x: true};
521 - },
522 - render: function() {
523 - return <span />;
524 - },
525 - });
526 - expect(() =>
527 - ReactTestUtils.renderIntoDocument(<Component />)).not.toThrow();
528 -
529 - instance = ReactTestUtils.renderIntoDocument(<Component />);
530 - expect(instance.state).toEqual({foo: 'bar', x: true});
531 - });
532 -});