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