react 0.12.2 → 0.13.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/JSXTransformer.js +6 -4
- package/dist/react-with-addons.js +4022 -3267
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +3853 -3358
- package/dist/react.min.js +6 -6
- package/lib/BeforeInputEventPlugin.js +388 -111
- package/lib/CSSPropertyOperations.js +20 -0
- package/lib/ChangeEventPlugin.js +2 -2
- package/lib/Danger.js +1 -1
- package/lib/DefaultEventPluginOrder.js +0 -1
- package/lib/ExecutionEnvironment.js +2 -3
- package/lib/FallbackCompositionState.js +87 -0
- package/lib/HTMLDOMPropertyConfig.js +1 -0
- package/lib/Object.assign.js +3 -1
- package/lib/React.js +14 -49
- package/lib/ReactBrowserComponentMixin.js +2 -12
- package/lib/ReactBrowserEventEmitter.js +2 -4
- package/lib/ReactCSSTransitionGroup.js +3 -0
- package/lib/ReactCSSTransitionGroupChild.js +8 -0
- package/lib/ReactChildReconciler.js +121 -0
- package/lib/ReactClass.js +916 -0
- package/lib/ReactComponent.js +36 -286
- package/lib/ReactComponentBrowserEnvironment.js +9 -82
- package/lib/ReactComponentEnvironment.js +57 -0
- package/lib/ReactCompositeComponent.js +608 -1026
- package/lib/ReactContext.js +5 -1
- package/lib/ReactDOM.js +2 -7
- package/lib/ReactDOMButton.js +4 -5
- package/lib/ReactDOMComponent.js +97 -69
- package/lib/ReactDOMForm.js +4 -5
- package/lib/ReactDOMIDOperations.js +55 -73
- package/lib/ReactDOMImg.js +3 -5
- package/lib/ReactDOMInput.js +4 -5
- package/lib/ReactDOMOption.js +4 -5
- package/lib/ReactDOMSelect.js +55 -63
- package/lib/ReactDOMSelection.js +5 -1
- package/lib/{ReactTextComponent.js → ReactDOMTextComponent.js} +54 -34
- package/lib/ReactDOMTextarea.js +4 -5
- package/lib/ReactDefaultInjection.js +13 -7
- package/lib/ReactDefaultPerf.js +6 -5
- package/lib/ReactDefaultPerfAnalysis.js +1 -1
- package/lib/ReactElement.js +17 -11
- package/lib/ReactElementValidator.js +74 -37
- package/lib/ReactEmptyComponent.js +17 -10
- package/lib/ReactInjection.js +6 -4
- package/lib/ReactInputSelection.js +2 -3
- package/lib/ReactInstanceMap.js +47 -0
- package/lib/ReactMount.js +193 -64
- package/lib/ReactMultiChild.js +32 -42
- package/lib/ReactNativeComponent.js +45 -8
- package/lib/ReactOwner.js +3 -47
- package/lib/ReactPerf.js +20 -0
- package/lib/ReactPropTransferer.js +0 -55
- package/lib/ReactPropTypes.js +1 -17
- package/lib/ReactRef.js +96 -0
- package/lib/ReactServerRendering.js +3 -2
- package/lib/ReactTestUtils.js +82 -25
- package/lib/ReactTransitionGroup.js +47 -6
- package/lib/ReactUpdates.js +43 -42
- package/lib/SyntheticMouseEvent.js +1 -3
- package/lib/ViewportMetrics.js +1 -4
- package/lib/accumulate.js +47 -0
- package/lib/cloneWithProps.js +2 -2
- package/lib/copyProperties.js +2 -0
- package/lib/createFullPageComponent.js +2 -2
- package/lib/findDOMNode.js +52 -0
- package/lib/flattenChildren.js +1 -14
- package/lib/getIteratorFn.js +42 -0
- package/lib/instantiateReactComponent.js +88 -65
- package/lib/isNode.js +3 -4
- package/lib/isTextInputElement.js +1 -2
- package/lib/shouldUpdateReactComponent.js +13 -5
- package/lib/traverseAllChildren.js +110 -54
- package/package.json +1 -1
- package/lib/CompositionEventPlugin.js +0 -257
- package/lib/ReactLegacyElement.js +0 -243
- package/lib/deprecated.js +0 -47
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2014, 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 ReactComponentEnvironment
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
var invariant = require("./invariant");
|
|
15
|
+
|
|
16
|
+
var injected = false;
|
|
17
|
+
|
|
18
|
+
var ReactComponentEnvironment = {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Optionally injectable environment dependent cleanup hook. (server vs.
|
|
22
|
+
* browser etc). Example: A browser system caches DOM nodes based on component
|
|
23
|
+
* ID and must remove that cache entry when this instance is unmounted.
|
|
24
|
+
*/
|
|
25
|
+
unmountIDFromEnvironment: null,
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Optionally injectable hook for swapping out mount images in the middle of
|
|
29
|
+
* the tree.
|
|
30
|
+
*/
|
|
31
|
+
replaceNodeWithMarkupByID: null,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Optionally injectable hook for processing a queue of child updates. Will
|
|
35
|
+
* later move into MultiChildComponents.
|
|
36
|
+
*/
|
|
37
|
+
processChildrenUpdates: null,
|
|
38
|
+
|
|
39
|
+
injection: {
|
|
40
|
+
injectEnvironment: function(environment) {
|
|
41
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
42
|
+
!injected,
|
|
43
|
+
'ReactCompositeComponent: injectEnvironment() can only be called once.'
|
|
44
|
+
) : invariant(!injected));
|
|
45
|
+
ReactComponentEnvironment.unmountIDFromEnvironment =
|
|
46
|
+
environment.unmountIDFromEnvironment;
|
|
47
|
+
ReactComponentEnvironment.replaceNodeWithMarkupByID =
|
|
48
|
+
environment.replaceNodeWithMarkupByID;
|
|
49
|
+
ReactComponentEnvironment.processChildrenUpdates =
|
|
50
|
+
environment.processChildrenUpdates;
|
|
51
|
+
injected = true;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
module.exports = ReactComponentEnvironment;
|
|
@@ -12,446 +12,36 @@
|
|
|
12
12
|
"use strict";
|
|
13
13
|
|
|
14
14
|
var ReactComponent = require("./ReactComponent");
|
|
15
|
+
var ReactComponentEnvironment = require("./ReactComponentEnvironment");
|
|
15
16
|
var ReactContext = require("./ReactContext");
|
|
16
17
|
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
17
18
|
var ReactElement = require("./ReactElement");
|
|
18
|
-
var
|
|
19
|
-
var ReactEmptyComponent = require("./ReactEmptyComponent");
|
|
20
|
-
var ReactErrorUtils = require("./ReactErrorUtils");
|
|
21
|
-
var ReactLegacyElement = require("./ReactLegacyElement");
|
|
22
|
-
var ReactOwner = require("./ReactOwner");
|
|
19
|
+
var ReactInstanceMap = require("./ReactInstanceMap");
|
|
23
20
|
var ReactPerf = require("./ReactPerf");
|
|
24
|
-
var ReactPropTransferer = require("./ReactPropTransferer");
|
|
25
21
|
var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
26
|
-
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
27
22
|
var ReactUpdates = require("./ReactUpdates");
|
|
28
23
|
|
|
29
24
|
var assign = require("./Object.assign");
|
|
30
|
-
var
|
|
25
|
+
var emptyObject = require("./emptyObject");
|
|
31
26
|
var invariant = require("./invariant");
|
|
32
27
|
var keyMirror = require("./keyMirror");
|
|
33
|
-
var keyOf = require("./keyOf");
|
|
34
|
-
var monitorCodeUse = require("./monitorCodeUse");
|
|
35
|
-
var mapObject = require("./mapObject");
|
|
36
28
|
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
37
29
|
var warning = require("./warning");
|
|
38
30
|
|
|
39
|
-
var MIXINS_KEY = keyOf({mixins: null});
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Policies that describe methods in `ReactCompositeComponentInterface`.
|
|
43
|
-
*/
|
|
44
|
-
var SpecPolicy = keyMirror({
|
|
45
|
-
/**
|
|
46
|
-
* These methods may be defined only once by the class specification or mixin.
|
|
47
|
-
*/
|
|
48
|
-
DEFINE_ONCE: null,
|
|
49
|
-
/**
|
|
50
|
-
* These methods may be defined by both the class specification and mixins.
|
|
51
|
-
* Subsequent definitions will be chained. These methods must return void.
|
|
52
|
-
*/
|
|
53
|
-
DEFINE_MANY: null,
|
|
54
|
-
/**
|
|
55
|
-
* These methods are overriding the base ReactCompositeComponent class.
|
|
56
|
-
*/
|
|
57
|
-
OVERRIDE_BASE: null,
|
|
58
|
-
/**
|
|
59
|
-
* These methods are similar to DEFINE_MANY, except we assume they return
|
|
60
|
-
* objects. We try to merge the keys of the return values of all the mixed in
|
|
61
|
-
* functions. If there is a key conflict we throw.
|
|
62
|
-
*/
|
|
63
|
-
DEFINE_MANY_MERGED: null
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
var injectedMixins = [];
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Composite components are higher-level components that compose other composite
|
|
71
|
-
* or native components.
|
|
72
|
-
*
|
|
73
|
-
* To create a new type of `ReactCompositeComponent`, pass a specification of
|
|
74
|
-
* your new class to `React.createClass`. The only requirement of your class
|
|
75
|
-
* specification is that you implement a `render` method.
|
|
76
|
-
*
|
|
77
|
-
* var MyComponent = React.createClass({
|
|
78
|
-
* render: function() {
|
|
79
|
-
* return <div>Hello World</div>;
|
|
80
|
-
* }
|
|
81
|
-
* });
|
|
82
|
-
*
|
|
83
|
-
* The class specification supports a specific protocol of methods that have
|
|
84
|
-
* special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for
|
|
85
|
-
* more the comprehensive protocol. Any other properties and methods in the
|
|
86
|
-
* class specification will available on the prototype.
|
|
87
|
-
*
|
|
88
|
-
* @interface ReactCompositeComponentInterface
|
|
89
|
-
* @internal
|
|
90
|
-
*/
|
|
91
|
-
var ReactCompositeComponentInterface = {
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* An array of Mixin objects to include when defining your component.
|
|
95
|
-
*
|
|
96
|
-
* @type {array}
|
|
97
|
-
* @optional
|
|
98
|
-
*/
|
|
99
|
-
mixins: SpecPolicy.DEFINE_MANY,
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* An object containing properties and methods that should be defined on
|
|
103
|
-
* the component's constructor instead of its prototype (static methods).
|
|
104
|
-
*
|
|
105
|
-
* @type {object}
|
|
106
|
-
* @optional
|
|
107
|
-
*/
|
|
108
|
-
statics: SpecPolicy.DEFINE_MANY,
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Definition of prop types for this component.
|
|
112
|
-
*
|
|
113
|
-
* @type {object}
|
|
114
|
-
* @optional
|
|
115
|
-
*/
|
|
116
|
-
propTypes: SpecPolicy.DEFINE_MANY,
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Definition of context types for this component.
|
|
120
|
-
*
|
|
121
|
-
* @type {object}
|
|
122
|
-
* @optional
|
|
123
|
-
*/
|
|
124
|
-
contextTypes: SpecPolicy.DEFINE_MANY,
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Definition of context types this component sets for its children.
|
|
128
|
-
*
|
|
129
|
-
* @type {object}
|
|
130
|
-
* @optional
|
|
131
|
-
*/
|
|
132
|
-
childContextTypes: SpecPolicy.DEFINE_MANY,
|
|
133
|
-
|
|
134
|
-
// ==== Definition methods ====
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Invoked when the component is mounted. Values in the mapping will be set on
|
|
138
|
-
* `this.props` if that prop is not specified (i.e. using an `in` check).
|
|
139
|
-
*
|
|
140
|
-
* This method is invoked before `getInitialState` and therefore cannot rely
|
|
141
|
-
* on `this.state` or use `this.setState`.
|
|
142
|
-
*
|
|
143
|
-
* @return {object}
|
|
144
|
-
* @optional
|
|
145
|
-
*/
|
|
146
|
-
getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Invoked once before the component is mounted. The return value will be used
|
|
150
|
-
* as the initial value of `this.state`.
|
|
151
|
-
*
|
|
152
|
-
* getInitialState: function() {
|
|
153
|
-
* return {
|
|
154
|
-
* isOn: false,
|
|
155
|
-
* fooBaz: new BazFoo()
|
|
156
|
-
* }
|
|
157
|
-
* }
|
|
158
|
-
*
|
|
159
|
-
* @return {object}
|
|
160
|
-
* @optional
|
|
161
|
-
*/
|
|
162
|
-
getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* @return {object}
|
|
166
|
-
* @optional
|
|
167
|
-
*/
|
|
168
|
-
getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Uses props from `this.props` and state from `this.state` to render the
|
|
172
|
-
* structure of the component.
|
|
173
|
-
*
|
|
174
|
-
* No guarantees are made about when or how often this method is invoked, so
|
|
175
|
-
* it must not have side effects.
|
|
176
|
-
*
|
|
177
|
-
* render: function() {
|
|
178
|
-
* var name = this.props.name;
|
|
179
|
-
* return <div>Hello, {name}!</div>;
|
|
180
|
-
* }
|
|
181
|
-
*
|
|
182
|
-
* @return {ReactComponent}
|
|
183
|
-
* @nosideeffects
|
|
184
|
-
* @required
|
|
185
|
-
*/
|
|
186
|
-
render: SpecPolicy.DEFINE_ONCE,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
// ==== Delegate methods ====
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Invoked when the component is initially created and about to be mounted.
|
|
194
|
-
* This may have side effects, but any external subscriptions or data created
|
|
195
|
-
* by this method must be cleaned up in `componentWillUnmount`.
|
|
196
|
-
*
|
|
197
|
-
* @optional
|
|
198
|
-
*/
|
|
199
|
-
componentWillMount: SpecPolicy.DEFINE_MANY,
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Invoked when the component has been mounted and has a DOM representation.
|
|
203
|
-
* However, there is no guarantee that the DOM node is in the document.
|
|
204
|
-
*
|
|
205
|
-
* Use this as an opportunity to operate on the DOM when the component has
|
|
206
|
-
* been mounted (initialized and rendered) for the first time.
|
|
207
|
-
*
|
|
208
|
-
* @param {DOMElement} rootNode DOM element representing the component.
|
|
209
|
-
* @optional
|
|
210
|
-
*/
|
|
211
|
-
componentDidMount: SpecPolicy.DEFINE_MANY,
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Invoked before the component receives new props.
|
|
215
|
-
*
|
|
216
|
-
* Use this as an opportunity to react to a prop transition by updating the
|
|
217
|
-
* state using `this.setState`. Current props are accessed via `this.props`.
|
|
218
|
-
*
|
|
219
|
-
* componentWillReceiveProps: function(nextProps, nextContext) {
|
|
220
|
-
* this.setState({
|
|
221
|
-
* likesIncreasing: nextProps.likeCount > this.props.likeCount
|
|
222
|
-
* });
|
|
223
|
-
* }
|
|
224
|
-
*
|
|
225
|
-
* NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
|
|
226
|
-
* transition may cause a state change, but the opposite is not true. If you
|
|
227
|
-
* need it, you are probably looking for `componentWillUpdate`.
|
|
228
|
-
*
|
|
229
|
-
* @param {object} nextProps
|
|
230
|
-
* @optional
|
|
231
|
-
*/
|
|
232
|
-
componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Invoked while deciding if the component should be updated as a result of
|
|
236
|
-
* receiving new props, state and/or context.
|
|
237
|
-
*
|
|
238
|
-
* Use this as an opportunity to `return false` when you're certain that the
|
|
239
|
-
* transition to the new props/state/context will not require a component
|
|
240
|
-
* update.
|
|
241
|
-
*
|
|
242
|
-
* shouldComponentUpdate: function(nextProps, nextState, nextContext) {
|
|
243
|
-
* return !equal(nextProps, this.props) ||
|
|
244
|
-
* !equal(nextState, this.state) ||
|
|
245
|
-
* !equal(nextContext, this.context);
|
|
246
|
-
* }
|
|
247
|
-
*
|
|
248
|
-
* @param {object} nextProps
|
|
249
|
-
* @param {?object} nextState
|
|
250
|
-
* @param {?object} nextContext
|
|
251
|
-
* @return {boolean} True if the component should update.
|
|
252
|
-
* @optional
|
|
253
|
-
*/
|
|
254
|
-
shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Invoked when the component is about to update due to a transition from
|
|
258
|
-
* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
|
|
259
|
-
* and `nextContext`.
|
|
260
|
-
*
|
|
261
|
-
* Use this as an opportunity to perform preparation before an update occurs.
|
|
262
|
-
*
|
|
263
|
-
* NOTE: You **cannot** use `this.setState()` in this method.
|
|
264
|
-
*
|
|
265
|
-
* @param {object} nextProps
|
|
266
|
-
* @param {?object} nextState
|
|
267
|
-
* @param {?object} nextContext
|
|
268
|
-
* @param {ReactReconcileTransaction} transaction
|
|
269
|
-
* @optional
|
|
270
|
-
*/
|
|
271
|
-
componentWillUpdate: SpecPolicy.DEFINE_MANY,
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Invoked when the component's DOM representation has been updated.
|
|
275
|
-
*
|
|
276
|
-
* Use this as an opportunity to operate on the DOM when the component has
|
|
277
|
-
* been updated.
|
|
278
|
-
*
|
|
279
|
-
* @param {object} prevProps
|
|
280
|
-
* @param {?object} prevState
|
|
281
|
-
* @param {?object} prevContext
|
|
282
|
-
* @param {DOMElement} rootNode DOM element representing the component.
|
|
283
|
-
* @optional
|
|
284
|
-
*/
|
|
285
|
-
componentDidUpdate: SpecPolicy.DEFINE_MANY,
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Invoked when the component is about to be removed from its parent and have
|
|
289
|
-
* its DOM representation destroyed.
|
|
290
|
-
*
|
|
291
|
-
* Use this as an opportunity to deallocate any external resources.
|
|
292
|
-
*
|
|
293
|
-
* NOTE: There is no `componentDidUnmount` since your component will have been
|
|
294
|
-
* destroyed by that point.
|
|
295
|
-
*
|
|
296
|
-
* @optional
|
|
297
|
-
*/
|
|
298
|
-
componentWillUnmount: SpecPolicy.DEFINE_MANY,
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
// ==== Advanced methods ====
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Updates the component's currently mounted DOM representation.
|
|
306
|
-
*
|
|
307
|
-
* By default, this implements React's rendering and reconciliation algorithm.
|
|
308
|
-
* Sophisticated clients may wish to override this.
|
|
309
|
-
*
|
|
310
|
-
* @param {ReactReconcileTransaction} transaction
|
|
311
|
-
* @internal
|
|
312
|
-
* @overridable
|
|
313
|
-
*/
|
|
314
|
-
updateComponent: SpecPolicy.OVERRIDE_BASE
|
|
315
|
-
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Mapping from class specification keys to special processing functions.
|
|
320
|
-
*
|
|
321
|
-
* Although these are declared like instance properties in the specification
|
|
322
|
-
* when defining classes using `React.createClass`, they are actually static
|
|
323
|
-
* and are accessible on the constructor instead of the prototype. Despite
|
|
324
|
-
* being static, they must be defined outside of the "statics" key under
|
|
325
|
-
* which all other static methods are defined.
|
|
326
|
-
*/
|
|
327
|
-
var RESERVED_SPEC_KEYS = {
|
|
328
|
-
displayName: function(Constructor, displayName) {
|
|
329
|
-
Constructor.displayName = displayName;
|
|
330
|
-
},
|
|
331
|
-
mixins: function(Constructor, mixins) {
|
|
332
|
-
if (mixins) {
|
|
333
|
-
for (var i = 0; i < mixins.length; i++) {
|
|
334
|
-
mixSpecIntoComponent(Constructor, mixins[i]);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
childContextTypes: function(Constructor, childContextTypes) {
|
|
339
|
-
validateTypeDef(
|
|
340
|
-
Constructor,
|
|
341
|
-
childContextTypes,
|
|
342
|
-
ReactPropTypeLocations.childContext
|
|
343
|
-
);
|
|
344
|
-
Constructor.childContextTypes = assign(
|
|
345
|
-
{},
|
|
346
|
-
Constructor.childContextTypes,
|
|
347
|
-
childContextTypes
|
|
348
|
-
);
|
|
349
|
-
},
|
|
350
|
-
contextTypes: function(Constructor, contextTypes) {
|
|
351
|
-
validateTypeDef(
|
|
352
|
-
Constructor,
|
|
353
|
-
contextTypes,
|
|
354
|
-
ReactPropTypeLocations.context
|
|
355
|
-
);
|
|
356
|
-
Constructor.contextTypes = assign(
|
|
357
|
-
{},
|
|
358
|
-
Constructor.contextTypes,
|
|
359
|
-
contextTypes
|
|
360
|
-
);
|
|
361
|
-
},
|
|
362
|
-
/**
|
|
363
|
-
* Special case getDefaultProps which should move into statics but requires
|
|
364
|
-
* automatic merging.
|
|
365
|
-
*/
|
|
366
|
-
getDefaultProps: function(Constructor, getDefaultProps) {
|
|
367
|
-
if (Constructor.getDefaultProps) {
|
|
368
|
-
Constructor.getDefaultProps = createMergedResultFunction(
|
|
369
|
-
Constructor.getDefaultProps,
|
|
370
|
-
getDefaultProps
|
|
371
|
-
);
|
|
372
|
-
} else {
|
|
373
|
-
Constructor.getDefaultProps = getDefaultProps;
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
propTypes: function(Constructor, propTypes) {
|
|
377
|
-
validateTypeDef(
|
|
378
|
-
Constructor,
|
|
379
|
-
propTypes,
|
|
380
|
-
ReactPropTypeLocations.prop
|
|
381
|
-
);
|
|
382
|
-
Constructor.propTypes = assign(
|
|
383
|
-
{},
|
|
384
|
-
Constructor.propTypes,
|
|
385
|
-
propTypes
|
|
386
|
-
);
|
|
387
|
-
},
|
|
388
|
-
statics: function(Constructor, statics) {
|
|
389
|
-
mixStaticSpecIntoComponent(Constructor, statics);
|
|
390
|
-
}
|
|
391
|
-
};
|
|
392
|
-
|
|
393
31
|
function getDeclarationErrorAddendum(component) {
|
|
394
|
-
var owner = component._owner || null;
|
|
395
|
-
if (owner
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function validateTypeDef(Constructor, typeDef, location) {
|
|
403
|
-
for (var propName in typeDef) {
|
|
404
|
-
if (typeDef.hasOwnProperty(propName)) {
|
|
405
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
406
|
-
typeof typeDef[propName] == 'function',
|
|
407
|
-
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
|
|
408
|
-
'React.PropTypes.',
|
|
409
|
-
Constructor.displayName || 'ReactCompositeComponent',
|
|
410
|
-
ReactPropTypeLocationNames[location],
|
|
411
|
-
propName
|
|
412
|
-
) : invariant(typeof typeDef[propName] == 'function'));
|
|
32
|
+
var owner = component._currentElement._owner || null;
|
|
33
|
+
if (owner) {
|
|
34
|
+
var constructor = owner._instance.constructor;
|
|
35
|
+
var name = constructor && (constructor.displayName || constructor.name);
|
|
36
|
+
if (name) {
|
|
37
|
+
return ' Check the render method of `' + name + '`.';
|
|
413
38
|
}
|
|
414
39
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
function validateMethodOverride(proto, name) {
|
|
418
|
-
var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
|
|
419
|
-
ReactCompositeComponentInterface[name] :
|
|
420
|
-
null;
|
|
421
|
-
|
|
422
|
-
// Disallow overriding of base class methods unless explicitly allowed.
|
|
423
|
-
if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
|
|
424
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
425
|
-
specPolicy === SpecPolicy.OVERRIDE_BASE,
|
|
426
|
-
'ReactCompositeComponentInterface: You are attempting to override ' +
|
|
427
|
-
'`%s` from your class specification. Ensure that your method names ' +
|
|
428
|
-
'do not overlap with React methods.',
|
|
429
|
-
name
|
|
430
|
-
) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Disallow defining methods more than once unless explicitly allowed.
|
|
434
|
-
if (proto.hasOwnProperty(name)) {
|
|
435
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
436
|
-
specPolicy === SpecPolicy.DEFINE_MANY ||
|
|
437
|
-
specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
|
|
438
|
-
'ReactCompositeComponentInterface: You are attempting to define ' +
|
|
439
|
-
'`%s` on your component more than once. This conflict may be due ' +
|
|
440
|
-
'to a mixin.',
|
|
441
|
-
name
|
|
442
|
-
) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||
|
|
443
|
-
specPolicy === SpecPolicy.DEFINE_MANY_MERGED));
|
|
444
|
-
}
|
|
40
|
+
return '';
|
|
445
41
|
}
|
|
446
42
|
|
|
447
43
|
function validateLifeCycleOnReplaceState(instance) {
|
|
448
44
|
var compositeLifeCycleState = instance._compositeLifeCycleState;
|
|
449
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
450
|
-
instance.isMounted() ||
|
|
451
|
-
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
|
|
452
|
-
'replaceState(...): Can only update a mounted or mounting component.'
|
|
453
|
-
) : invariant(instance.isMounted() ||
|
|
454
|
-
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
|
|
455
45
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
456
46
|
ReactCurrentOwner.current == null,
|
|
457
47
|
'replaceState(...): Cannot update during an existing state transition ' +
|
|
@@ -464,215 +54,12 @@ function validateLifeCycleOnReplaceState(instance) {
|
|
|
464
54
|
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
|
|
465
55
|
}
|
|
466
56
|
|
|
467
|
-
/**
|
|
468
|
-
* Mixin helper which handles policy validation and reserved
|
|
469
|
-
* specification keys when building `ReactCompositeComponent` classses.
|
|
470
|
-
*/
|
|
471
|
-
function mixSpecIntoComponent(Constructor, spec) {
|
|
472
|
-
if (!spec) {
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
477
|
-
!ReactLegacyElement.isValidFactory(spec),
|
|
478
|
-
'ReactCompositeComponent: You\'re attempting to ' +
|
|
479
|
-
'use a component class as a mixin. Instead, just use a regular object.'
|
|
480
|
-
) : invariant(!ReactLegacyElement.isValidFactory(spec)));
|
|
481
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
482
|
-
!ReactElement.isValidElement(spec),
|
|
483
|
-
'ReactCompositeComponent: You\'re attempting to ' +
|
|
484
|
-
'use a component as a mixin. Instead, just use a regular object.'
|
|
485
|
-
) : invariant(!ReactElement.isValidElement(spec)));
|
|
486
|
-
|
|
487
|
-
var proto = Constructor.prototype;
|
|
488
|
-
|
|
489
|
-
// By handling mixins before any other properties, we ensure the same
|
|
490
|
-
// chaining order is applied to methods with DEFINE_MANY policy, whether
|
|
491
|
-
// mixins are listed before or after these methods in the spec.
|
|
492
|
-
if (spec.hasOwnProperty(MIXINS_KEY)) {
|
|
493
|
-
RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
for (var name in spec) {
|
|
497
|
-
if (!spec.hasOwnProperty(name)) {
|
|
498
|
-
continue;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (name === MIXINS_KEY) {
|
|
502
|
-
// We have already handled mixins in a special case above
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
var property = spec[name];
|
|
507
|
-
validateMethodOverride(proto, name);
|
|
508
|
-
|
|
509
|
-
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
|
|
510
|
-
RESERVED_SPEC_KEYS[name](Constructor, property);
|
|
511
|
-
} else {
|
|
512
|
-
// Setup methods on prototype:
|
|
513
|
-
// The following member methods should not be automatically bound:
|
|
514
|
-
// 1. Expected ReactCompositeComponent methods (in the "interface").
|
|
515
|
-
// 2. Overridden methods (that were mixed in).
|
|
516
|
-
var isCompositeComponentMethod =
|
|
517
|
-
ReactCompositeComponentInterface.hasOwnProperty(name);
|
|
518
|
-
var isAlreadyDefined = proto.hasOwnProperty(name);
|
|
519
|
-
var markedDontBind = property && property.__reactDontBind;
|
|
520
|
-
var isFunction = typeof property === 'function';
|
|
521
|
-
var shouldAutoBind =
|
|
522
|
-
isFunction &&
|
|
523
|
-
!isCompositeComponentMethod &&
|
|
524
|
-
!isAlreadyDefined &&
|
|
525
|
-
!markedDontBind;
|
|
526
|
-
|
|
527
|
-
if (shouldAutoBind) {
|
|
528
|
-
if (!proto.__reactAutoBindMap) {
|
|
529
|
-
proto.__reactAutoBindMap = {};
|
|
530
|
-
}
|
|
531
|
-
proto.__reactAutoBindMap[name] = property;
|
|
532
|
-
proto[name] = property;
|
|
533
|
-
} else {
|
|
534
|
-
if (isAlreadyDefined) {
|
|
535
|
-
var specPolicy = ReactCompositeComponentInterface[name];
|
|
536
|
-
|
|
537
|
-
// These cases should already be caught by validateMethodOverride
|
|
538
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
539
|
-
isCompositeComponentMethod && (
|
|
540
|
-
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
|
|
541
|
-
specPolicy === SpecPolicy.DEFINE_MANY
|
|
542
|
-
),
|
|
543
|
-
'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
|
|
544
|
-
'when mixing in component specs.',
|
|
545
|
-
specPolicy,
|
|
546
|
-
name
|
|
547
|
-
) : invariant(isCompositeComponentMethod && (
|
|
548
|
-
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
|
|
549
|
-
specPolicy === SpecPolicy.DEFINE_MANY
|
|
550
|
-
)));
|
|
551
|
-
|
|
552
|
-
// For methods which are defined more than once, call the existing
|
|
553
|
-
// methods before calling the new property, merging if appropriate.
|
|
554
|
-
if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
|
|
555
|
-
proto[name] = createMergedResultFunction(proto[name], property);
|
|
556
|
-
} else if (specPolicy === SpecPolicy.DEFINE_MANY) {
|
|
557
|
-
proto[name] = createChainedFunction(proto[name], property);
|
|
558
|
-
}
|
|
559
|
-
} else {
|
|
560
|
-
proto[name] = property;
|
|
561
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
562
|
-
// Add verbose displayName to the function, which helps when looking
|
|
563
|
-
// at profiling tools.
|
|
564
|
-
if (typeof property === 'function' && spec.displayName) {
|
|
565
|
-
proto[name].displayName = spec.displayName + '_' + name;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
function mixStaticSpecIntoComponent(Constructor, statics) {
|
|
575
|
-
if (!statics) {
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
for (var name in statics) {
|
|
579
|
-
var property = statics[name];
|
|
580
|
-
if (!statics.hasOwnProperty(name)) {
|
|
581
|
-
continue;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
var isReserved = name in RESERVED_SPEC_KEYS;
|
|
585
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
586
|
-
!isReserved,
|
|
587
|
-
'ReactCompositeComponent: You are attempting to define a reserved ' +
|
|
588
|
-
'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
|
|
589
|
-
'as an instance property instead; it will still be accessible on the ' +
|
|
590
|
-
'constructor.',
|
|
591
|
-
name
|
|
592
|
-
) : invariant(!isReserved));
|
|
593
|
-
|
|
594
|
-
var isInherited = name in Constructor;
|
|
595
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
596
|
-
!isInherited,
|
|
597
|
-
'ReactCompositeComponent: You are attempting to define ' +
|
|
598
|
-
'`%s` on your component more than once. This conflict may be ' +
|
|
599
|
-
'due to a mixin.',
|
|
600
|
-
name
|
|
601
|
-
) : invariant(!isInherited));
|
|
602
|
-
Constructor[name] = property;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/**
|
|
607
|
-
* Merge two objects, but throw if both contain the same key.
|
|
608
|
-
*
|
|
609
|
-
* @param {object} one The first object, which is mutated.
|
|
610
|
-
* @param {object} two The second object
|
|
611
|
-
* @return {object} one after it has been mutated to contain everything in two.
|
|
612
|
-
*/
|
|
613
|
-
function mergeObjectsWithNoDuplicateKeys(one, two) {
|
|
614
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
615
|
-
one && two && typeof one === 'object' && typeof two === 'object',
|
|
616
|
-
'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
|
|
617
|
-
) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
|
|
618
|
-
|
|
619
|
-
mapObject(two, function(value, key) {
|
|
620
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
621
|
-
one[key] === undefined,
|
|
622
|
-
'mergeObjectsWithNoDuplicateKeys(): ' +
|
|
623
|
-
'Tried to merge two objects with the same key: `%s`. This conflict ' +
|
|
624
|
-
'may be due to a mixin; in particular, this may be caused by two ' +
|
|
625
|
-
'getInitialState() or getDefaultProps() methods returning objects ' +
|
|
626
|
-
'with clashing keys.',
|
|
627
|
-
key
|
|
628
|
-
) : invariant(one[key] === undefined));
|
|
629
|
-
one[key] = value;
|
|
630
|
-
});
|
|
631
|
-
return one;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Creates a function that invokes two functions and merges their return values.
|
|
636
|
-
*
|
|
637
|
-
* @param {function} one Function to invoke first.
|
|
638
|
-
* @param {function} two Function to invoke second.
|
|
639
|
-
* @return {function} Function that invokes the two argument functions.
|
|
640
|
-
* @private
|
|
641
|
-
*/
|
|
642
|
-
function createMergedResultFunction(one, two) {
|
|
643
|
-
return function mergedResult() {
|
|
644
|
-
var a = one.apply(this, arguments);
|
|
645
|
-
var b = two.apply(this, arguments);
|
|
646
|
-
if (a == null) {
|
|
647
|
-
return b;
|
|
648
|
-
} else if (b == null) {
|
|
649
|
-
return a;
|
|
650
|
-
}
|
|
651
|
-
return mergeObjectsWithNoDuplicateKeys(a, b);
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* Creates a function that invokes two functions and ignores their return vales.
|
|
657
|
-
*
|
|
658
|
-
* @param {function} one Function to invoke first.
|
|
659
|
-
* @param {function} two Function to invoke second.
|
|
660
|
-
* @return {function} Function that invokes the two argument functions.
|
|
661
|
-
* @private
|
|
662
|
-
*/
|
|
663
|
-
function createChainedFunction(one, two) {
|
|
664
|
-
return function chainedFunction() {
|
|
665
|
-
one.apply(this, arguments);
|
|
666
|
-
two.apply(this, arguments);
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
|
|
670
57
|
/**
|
|
671
58
|
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
|
|
672
59
|
* `this._compositeLifeCycleState` (which can be null).
|
|
673
60
|
*
|
|
674
|
-
* This is different from the life cycle state maintained by `ReactComponent
|
|
675
|
-
*
|
|
61
|
+
* This is different from the life cycle state maintained by `ReactComponent`.
|
|
62
|
+
* The following diagram shows how the states overlap in
|
|
676
63
|
* time. There are times when the CompositeLifeCycle is null - at those times it
|
|
677
64
|
* is only meaningful to look at ComponentLifeCycle alone.
|
|
678
65
|
*
|
|
@@ -711,10 +98,19 @@ var CompositeLifeCycle = keyMirror({
|
|
|
711
98
|
RECEIVING_PROPS: null
|
|
712
99
|
});
|
|
713
100
|
|
|
101
|
+
/**
|
|
102
|
+
* An incrementing ID assigned to each component when it is mounted. This is
|
|
103
|
+
* used to enforce the order in which `ReactUpdates` updates dirty components.
|
|
104
|
+
*
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
var nextMountID = 1;
|
|
108
|
+
|
|
714
109
|
/**
|
|
715
110
|
* @lends {ReactCompositeComponent.prototype}
|
|
716
111
|
*/
|
|
717
|
-
var ReactCompositeComponentMixin = {
|
|
112
|
+
var ReactCompositeComponentMixin = assign({},
|
|
113
|
+
ReactComponent.Mixin, {
|
|
718
114
|
|
|
719
115
|
/**
|
|
720
116
|
* Base constructor for all composite component.
|
|
@@ -724,18 +120,30 @@ var ReactCompositeComponentMixin = {
|
|
|
724
120
|
* @internal
|
|
725
121
|
*/
|
|
726
122
|
construct: function(element) {
|
|
727
|
-
|
|
728
|
-
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
729
|
-
ReactOwner.Mixin.construct.apply(this, arguments);
|
|
123
|
+
this._rootNodeID = null;
|
|
730
124
|
|
|
731
|
-
this.
|
|
125
|
+
this._instance.props = element.props;
|
|
126
|
+
this._instance.state = null;
|
|
127
|
+
this._instance.context = null;
|
|
128
|
+
this._instance.refs = emptyObject;
|
|
129
|
+
|
|
130
|
+
this._pendingElement = null;
|
|
131
|
+
this._pendingContext = null;
|
|
732
132
|
this._pendingState = null;
|
|
133
|
+
this._pendingForceUpdate = false;
|
|
134
|
+
this._compositeLifeCycleState = null;
|
|
733
135
|
|
|
734
|
-
|
|
735
|
-
// context lives on the element.
|
|
736
|
-
this.context = null;
|
|
136
|
+
this._renderedComponent = null;
|
|
737
137
|
|
|
738
|
-
|
|
138
|
+
// Children can be either an array or more than one argument
|
|
139
|
+
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
140
|
+
|
|
141
|
+
this._context = null;
|
|
142
|
+
this._mountOrder = 0;
|
|
143
|
+
this._isTopLevel = false;
|
|
144
|
+
|
|
145
|
+
// See ReactUpdates.
|
|
146
|
+
this._pendingCallbacks = null;
|
|
739
147
|
},
|
|
740
148
|
|
|
741
149
|
/**
|
|
@@ -745,8 +153,7 @@ var ReactCompositeComponentMixin = {
|
|
|
745
153
|
* @final
|
|
746
154
|
*/
|
|
747
155
|
isMounted: function() {
|
|
748
|
-
return
|
|
749
|
-
this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
|
|
156
|
+
return this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
|
|
750
157
|
},
|
|
751
158
|
|
|
752
159
|
/**
|
|
@@ -754,68 +161,83 @@ var ReactCompositeComponentMixin = {
|
|
|
754
161
|
*
|
|
755
162
|
* @param {string} rootID DOM ID of the root node.
|
|
756
163
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
757
|
-
* @param {number} mountDepth number of components in the owner hierarchy
|
|
758
164
|
* @return {?string} Rendered markup to be inserted into the DOM.
|
|
759
165
|
* @final
|
|
760
166
|
* @internal
|
|
761
167
|
*/
|
|
762
|
-
mountComponent:
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
transaction,
|
|
770
|
-
mountDepth
|
|
771
|
-
);
|
|
772
|
-
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
168
|
+
mountComponent: function(rootID, transaction, context) {
|
|
169
|
+
ReactComponent.Mixin.mountComponent.call(
|
|
170
|
+
this,
|
|
171
|
+
rootID,
|
|
172
|
+
transaction,
|
|
173
|
+
context
|
|
174
|
+
);
|
|
773
175
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
176
|
+
this._context = context;
|
|
177
|
+
this._mountOrder = nextMountID++;
|
|
178
|
+
this._rootNodeID = rootID;
|
|
777
179
|
|
|
778
|
-
|
|
779
|
-
this.props = this._processProps(this.props);
|
|
180
|
+
var inst = this._instance;
|
|
780
181
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
typeof this.state === 'object' && !Array.isArray(this.state),
|
|
784
|
-
'%s.getInitialState(): must return an object or null',
|
|
785
|
-
this.constructor.displayName || 'ReactCompositeComponent'
|
|
786
|
-
) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
|
|
787
|
-
|
|
788
|
-
this._pendingState = null;
|
|
789
|
-
this._pendingForceUpdate = false;
|
|
790
|
-
|
|
791
|
-
if (this.componentWillMount) {
|
|
792
|
-
this.componentWillMount();
|
|
793
|
-
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
794
|
-
// `this._pendingState` without triggering a re-render.
|
|
795
|
-
if (this._pendingState) {
|
|
796
|
-
this.state = this._pendingState;
|
|
797
|
-
this._pendingState = null;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
182
|
+
// Store a reference from the instance back to the internal representation
|
|
183
|
+
ReactInstanceMap.set(inst, this);
|
|
800
184
|
|
|
801
|
-
|
|
802
|
-
this._renderValidatedComponent(),
|
|
803
|
-
this._currentElement.type // The wrapping type
|
|
804
|
-
);
|
|
185
|
+
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
805
186
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
187
|
+
inst.context = this._processContext(this._currentElement._context);
|
|
188
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
189
|
+
this._warnIfContextsDiffer(this._currentElement._context, context);
|
|
190
|
+
}
|
|
191
|
+
inst.props = this._processProps(this._currentElement.props);
|
|
192
|
+
|
|
193
|
+
var initialState = inst.getInitialState ? inst.getInitialState() : null;
|
|
194
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
195
|
+
// We allow auto-mocks to proceed as if they're returning null.
|
|
196
|
+
if (typeof initialState === 'undefined' &&
|
|
197
|
+
inst.getInitialState._isMockFunction) {
|
|
198
|
+
// This is probably bad practice. Consider warning here and
|
|
199
|
+
// deprecating this convenience.
|
|
200
|
+
initialState = null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
204
|
+
typeof initialState === 'object' && !Array.isArray(initialState),
|
|
205
|
+
'%s.getInitialState(): must return an object or null',
|
|
206
|
+
inst.constructor.displayName || 'ReactCompositeComponent'
|
|
207
|
+
) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
|
|
208
|
+
inst.state = initialState;
|
|
209
|
+
|
|
210
|
+
this._pendingState = null;
|
|
211
|
+
this._pendingForceUpdate = false;
|
|
212
|
+
|
|
213
|
+
if (inst.componentWillMount) {
|
|
214
|
+
inst.componentWillMount();
|
|
215
|
+
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
216
|
+
// `this._pendingState` without triggering a re-render.
|
|
217
|
+
if (this._pendingState) {
|
|
218
|
+
inst.state = this._pendingState;
|
|
219
|
+
this._pendingState = null;
|
|
815
220
|
}
|
|
816
|
-
return markup;
|
|
817
221
|
}
|
|
818
|
-
|
|
222
|
+
|
|
223
|
+
var renderedElement = this._renderValidatedComponent();
|
|
224
|
+
this._renderedComponent = this._instantiateReactComponent(
|
|
225
|
+
renderedElement,
|
|
226
|
+
this._currentElement.type // The wrapping type
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Done with mounting, `setState` will now trigger UI changes.
|
|
230
|
+
this._compositeLifeCycleState = null;
|
|
231
|
+
var markup = this._renderedComponent.mountComponent(
|
|
232
|
+
rootID,
|
|
233
|
+
transaction,
|
|
234
|
+
this._processChildContext(context)
|
|
235
|
+
);
|
|
236
|
+
if (inst.componentDidMount) {
|
|
237
|
+
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
|
|
238
|
+
}
|
|
239
|
+
return markup;
|
|
240
|
+
},
|
|
819
241
|
|
|
820
242
|
/**
|
|
821
243
|
* Releases any resources allocated by `mountComponent`.
|
|
@@ -824,34 +246,110 @@ var ReactCompositeComponentMixin = {
|
|
|
824
246
|
* @internal
|
|
825
247
|
*/
|
|
826
248
|
unmountComponent: function() {
|
|
249
|
+
var inst = this._instance;
|
|
250
|
+
|
|
827
251
|
this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
|
|
828
|
-
if (
|
|
829
|
-
|
|
252
|
+
if (inst.componentWillUnmount) {
|
|
253
|
+
inst.componentWillUnmount();
|
|
830
254
|
}
|
|
831
255
|
this._compositeLifeCycleState = null;
|
|
832
256
|
|
|
833
257
|
this._renderedComponent.unmountComponent();
|
|
834
258
|
this._renderedComponent = null;
|
|
835
259
|
|
|
260
|
+
// Reset pending fields
|
|
261
|
+
this._pendingState = null;
|
|
262
|
+
this._pendingForceUpdate = false;
|
|
263
|
+
this._pendingCallbacks = null;
|
|
264
|
+
this._pendingElement = null;
|
|
265
|
+
|
|
836
266
|
ReactComponent.Mixin.unmountComponent.call(this);
|
|
837
267
|
|
|
838
|
-
|
|
268
|
+
ReactComponentEnvironment.unmountIDFromEnvironment(this._rootNodeID);
|
|
269
|
+
|
|
270
|
+
this._context = null;
|
|
271
|
+
this._rootNodeID = null;
|
|
272
|
+
|
|
273
|
+
// Delete the reference from the instance to this internal representation
|
|
274
|
+
// which allow the internals to be properly cleaned up even if the user
|
|
275
|
+
// leaks a reference to the public instance.
|
|
276
|
+
ReactInstanceMap.remove(inst);
|
|
277
|
+
|
|
278
|
+
// Some existing components rely on inst.props even after they've been
|
|
839
279
|
// destroyed (in event handlers).
|
|
840
|
-
// TODO:
|
|
841
|
-
// TODO:
|
|
280
|
+
// TODO: inst.props = null;
|
|
281
|
+
// TODO: inst.state = null;
|
|
282
|
+
// TODO: inst.context = null;
|
|
842
283
|
},
|
|
843
284
|
|
|
844
285
|
/**
|
|
845
|
-
* Sets a subset of the
|
|
846
|
-
* state. You should treat `this.state` as immutable.
|
|
286
|
+
* Sets a subset of the props.
|
|
847
287
|
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
288
|
+
* @param {object} partialProps Subset of the next props.
|
|
289
|
+
* @param {?function} callback Called after props are updated.
|
|
290
|
+
* @final
|
|
291
|
+
* @public
|
|
292
|
+
*/
|
|
293
|
+
setProps: function(partialProps, callback) {
|
|
294
|
+
// Merge with the pending element if it exists, otherwise with existing
|
|
295
|
+
// element props.
|
|
296
|
+
var element = this._pendingElement || this._currentElement;
|
|
297
|
+
this.replaceProps(
|
|
298
|
+
assign({}, element.props, partialProps),
|
|
299
|
+
callback
|
|
300
|
+
);
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Replaces all of the props.
|
|
305
|
+
*
|
|
306
|
+
* @param {object} props New props.
|
|
307
|
+
* @param {?function} callback Called after props are updated.
|
|
308
|
+
* @final
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
replaceProps: function(props, callback) {
|
|
312
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
313
|
+
this._isTopLevel,
|
|
314
|
+
'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
|
|
315
|
+
'component with a parent. This is an anti-pattern since props will ' +
|
|
316
|
+
'get reactively updated when rendered. Instead, change the owner\'s ' +
|
|
317
|
+
'`render` method to pass the correct value as props to the component ' +
|
|
318
|
+
'where it is created.'
|
|
319
|
+
) : invariant(this._isTopLevel));
|
|
320
|
+
// This is a deoptimized path. We optimize for always having an element.
|
|
321
|
+
// This creates an extra internal element.
|
|
322
|
+
this._pendingElement = ReactElement.cloneAndReplaceProps(
|
|
323
|
+
this._pendingElement || this._currentElement,
|
|
324
|
+
props
|
|
325
|
+
);
|
|
326
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Schedule a partial update to the props. Only used for internal testing.
|
|
850
331
|
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
332
|
+
* @param {object} partialProps Subset of the next props.
|
|
333
|
+
* @param {?function} callback Called after props are updated.
|
|
334
|
+
* @final
|
|
335
|
+
* @internal
|
|
336
|
+
*/
|
|
337
|
+
_setPropsInternal: function(partialProps, callback) {
|
|
338
|
+
// This is a deoptimized path. We optimize for always having an element.
|
|
339
|
+
// This creates an extra internal element.
|
|
340
|
+
var element = this._pendingElement || this._currentElement;
|
|
341
|
+
this._pendingElement = ReactElement.cloneAndReplaceProps(
|
|
342
|
+
element,
|
|
343
|
+
assign({}, element.props, partialProps)
|
|
344
|
+
);
|
|
345
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Sets a subset of the state. This only exists because _pendingState is
|
|
350
|
+
* internal. This provides a merging strategy that is not available to deep
|
|
351
|
+
* properties which is confusing. TODO: Expose pendingState or don't use it
|
|
352
|
+
* during the merge.
|
|
855
353
|
*
|
|
856
354
|
* @param {object} partialState Next partial state to be merged with state.
|
|
857
355
|
* @param {?function} callback Called after state is updated.
|
|
@@ -859,20 +357,9 @@ var ReactCompositeComponentMixin = {
|
|
|
859
357
|
* @protected
|
|
860
358
|
*/
|
|
861
359
|
setState: function(partialState, callback) {
|
|
862
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
863
|
-
typeof partialState === 'object' || partialState == null,
|
|
864
|
-
'setState(...): takes an object of state variables to update.'
|
|
865
|
-
) : invariant(typeof partialState === 'object' || partialState == null));
|
|
866
|
-
if ("production" !== process.env.NODE_ENV){
|
|
867
|
-
("production" !== process.env.NODE_ENV ? warning(
|
|
868
|
-
partialState != null,
|
|
869
|
-
'setState(...): You passed an undefined or null state object; ' +
|
|
870
|
-
'instead, use forceUpdate().'
|
|
871
|
-
) : null);
|
|
872
|
-
}
|
|
873
360
|
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
874
361
|
this.replaceState(
|
|
875
|
-
assign({}, this._pendingState || this.state, partialState),
|
|
362
|
+
assign({}, this._pendingState || this._instance.state, partialState),
|
|
876
363
|
callback
|
|
877
364
|
);
|
|
878
365
|
},
|
|
@@ -903,6 +390,33 @@ var ReactCompositeComponentMixin = {
|
|
|
903
390
|
}
|
|
904
391
|
},
|
|
905
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Forces an update. This should only be invoked when it is known with
|
|
395
|
+
* certainty that we are **not** in a DOM transaction.
|
|
396
|
+
*
|
|
397
|
+
* You may want to call this when you know that some deeper aspect of the
|
|
398
|
+
* component's state has changed but `setState` was not called.
|
|
399
|
+
*
|
|
400
|
+
* This will not invoke `shouldUpdateComponent`, but it will invoke
|
|
401
|
+
* `componentWillUpdate` and `componentDidUpdate`.
|
|
402
|
+
*
|
|
403
|
+
* @param {?function} callback Called after update is complete.isM
|
|
404
|
+
* @final
|
|
405
|
+
* @protected
|
|
406
|
+
*/
|
|
407
|
+
forceUpdate: function(callback) {
|
|
408
|
+
var compositeLifeCycleState = this._compositeLifeCycleState;
|
|
409
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
410
|
+
compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
|
|
411
|
+
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
|
|
412
|
+
'forceUpdate(...): Cannot force an update while unmounting component ' +
|
|
413
|
+
'or during an existing state transition (such as within `render`).'
|
|
414
|
+
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
|
|
415
|
+
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
|
|
416
|
+
this._pendingForceUpdate = true;
|
|
417
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
418
|
+
},
|
|
419
|
+
|
|
906
420
|
/**
|
|
907
421
|
* Filters the context object to only contain keys specified in
|
|
908
422
|
* `contextTypes`, and asserts that they are valid.
|
|
@@ -913,19 +427,20 @@ var ReactCompositeComponentMixin = {
|
|
|
913
427
|
*/
|
|
914
428
|
_processContext: function(context) {
|
|
915
429
|
var maskedContext = null;
|
|
916
|
-
var contextTypes = this.constructor.contextTypes;
|
|
917
|
-
if (contextTypes) {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
430
|
+
var contextTypes = this._instance.constructor.contextTypes;
|
|
431
|
+
if (!contextTypes) {
|
|
432
|
+
return emptyObject;
|
|
433
|
+
}
|
|
434
|
+
maskedContext = {};
|
|
435
|
+
for (var contextName in contextTypes) {
|
|
436
|
+
maskedContext[contextName] = context[contextName];
|
|
437
|
+
}
|
|
438
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
439
|
+
this._checkPropTypes(
|
|
440
|
+
contextTypes,
|
|
441
|
+
maskedContext,
|
|
442
|
+
ReactPropTypeLocations.context
|
|
443
|
+
);
|
|
929
444
|
}
|
|
930
445
|
return maskedContext;
|
|
931
446
|
},
|
|
@@ -936,29 +451,30 @@ var ReactCompositeComponentMixin = {
|
|
|
936
451
|
* @private
|
|
937
452
|
*/
|
|
938
453
|
_processChildContext: function(currentContext) {
|
|
939
|
-
var
|
|
940
|
-
var
|
|
454
|
+
var inst = this._instance;
|
|
455
|
+
var childContext = inst.getChildContext && inst.getChildContext();
|
|
456
|
+
var displayName = inst.constructor.displayName || 'ReactCompositeComponent';
|
|
941
457
|
if (childContext) {
|
|
942
458
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
943
|
-
typeof
|
|
459
|
+
typeof inst.constructor.childContextTypes === 'object',
|
|
944
460
|
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
|
945
461
|
'use getChildContext().',
|
|
946
462
|
displayName
|
|
947
|
-
) : invariant(typeof
|
|
463
|
+
) : invariant(typeof inst.constructor.childContextTypes === 'object'));
|
|
948
464
|
if ("production" !== process.env.NODE_ENV) {
|
|
949
465
|
this._checkPropTypes(
|
|
950
|
-
|
|
466
|
+
inst.constructor.childContextTypes,
|
|
951
467
|
childContext,
|
|
952
468
|
ReactPropTypeLocations.childContext
|
|
953
469
|
);
|
|
954
470
|
}
|
|
955
471
|
for (var name in childContext) {
|
|
956
472
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
957
|
-
name in
|
|
473
|
+
name in inst.constructor.childContextTypes,
|
|
958
474
|
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
|
|
959
475
|
displayName,
|
|
960
476
|
name
|
|
961
|
-
) : invariant(name in
|
|
477
|
+
) : invariant(name in inst.constructor.childContextTypes));
|
|
962
478
|
}
|
|
963
479
|
return assign({}, currentContext, childContext);
|
|
964
480
|
}
|
|
@@ -976,7 +492,8 @@ var ReactCompositeComponentMixin = {
|
|
|
976
492
|
*/
|
|
977
493
|
_processProps: function(newProps) {
|
|
978
494
|
if ("production" !== process.env.NODE_ENV) {
|
|
979
|
-
var
|
|
495
|
+
var inst = this._instance;
|
|
496
|
+
var propTypes = inst.constructor.propTypes;
|
|
980
497
|
if (propTypes) {
|
|
981
498
|
this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop);
|
|
982
499
|
}
|
|
@@ -995,14 +512,15 @@ var ReactCompositeComponentMixin = {
|
|
|
995
512
|
_checkPropTypes: function(propTypes, props, location) {
|
|
996
513
|
// TODO: Stop validating prop types here and only use the element
|
|
997
514
|
// validation.
|
|
998
|
-
var componentName = this.constructor.displayName
|
|
515
|
+
var componentName = this._instance.constructor.displayName ||
|
|
516
|
+
this._instance.constructor.name;
|
|
999
517
|
for (var propName in propTypes) {
|
|
1000
518
|
if (propTypes.hasOwnProperty(propName)) {
|
|
1001
519
|
var error =
|
|
1002
520
|
propTypes[propName](props, propName, componentName, location);
|
|
1003
521
|
if (error instanceof Error) {
|
|
1004
522
|
// We may want to extend this logic for similar errors in
|
|
1005
|
-
//
|
|
523
|
+
// React.render calls, so I'm abstracting it away into
|
|
1006
524
|
// a function to minimize refactoring in the future
|
|
1007
525
|
var addendum = getDeclarationErrorAddendum(this);
|
|
1008
526
|
("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
|
|
@@ -1011,6 +529,24 @@ var ReactCompositeComponentMixin = {
|
|
|
1011
529
|
}
|
|
1012
530
|
},
|
|
1013
531
|
|
|
532
|
+
receiveComponent: function(nextElement, transaction, context) {
|
|
533
|
+
if (nextElement === this._currentElement &&
|
|
534
|
+
nextElement._owner != null) {
|
|
535
|
+
// Since elements are immutable after the owner is rendered,
|
|
536
|
+
// we can do a cheap identity compare here to determine if this is a
|
|
537
|
+
// superfluous reconcile. It's possible for state to be mutable but such
|
|
538
|
+
// change should trigger an update of the owner which would recreate
|
|
539
|
+
// the element. We explicitly check for the existence of an owner since
|
|
540
|
+
// it's possible for an element created outside a composite to be
|
|
541
|
+
// deeply mutated and reused.
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
this._pendingElement = nextElement;
|
|
546
|
+
this._pendingContext = context;
|
|
547
|
+
this.performUpdateIfNecessary(transaction);
|
|
548
|
+
},
|
|
549
|
+
|
|
1014
550
|
/**
|
|
1015
551
|
* If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate`
|
|
1016
552
|
* is set, update the component.
|
|
@@ -1029,67 +565,161 @@ var ReactCompositeComponentMixin = {
|
|
|
1029
565
|
|
|
1030
566
|
if (this._pendingElement == null &&
|
|
1031
567
|
this._pendingState == null &&
|
|
568
|
+
this._pendingContext == null &&
|
|
1032
569
|
!this._pendingForceUpdate) {
|
|
1033
570
|
return;
|
|
1034
571
|
}
|
|
1035
572
|
|
|
1036
|
-
var
|
|
1037
|
-
var
|
|
1038
|
-
var nextElement = this._currentElement;
|
|
573
|
+
var prevElement = this._currentElement;
|
|
574
|
+
var nextElement = prevElement;
|
|
1039
575
|
if (this._pendingElement != null) {
|
|
1040
576
|
nextElement = this._pendingElement;
|
|
1041
|
-
nextContext = this._processContext(nextElement._context);
|
|
1042
|
-
nextProps = this._processProps(nextElement.props);
|
|
1043
577
|
this._pendingElement = null;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
var prevContext = this._context;
|
|
581
|
+
var nextContext = prevContext;
|
|
582
|
+
if (this._pendingContext != null) {
|
|
583
|
+
nextContext = this._pendingContext;
|
|
584
|
+
this._pendingContext = null;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
this.updateComponent(
|
|
588
|
+
transaction,
|
|
589
|
+
prevElement,
|
|
590
|
+
nextElement,
|
|
591
|
+
prevContext,
|
|
592
|
+
nextContext
|
|
593
|
+
);
|
|
594
|
+
},
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Compare two contexts, warning if they are different
|
|
598
|
+
* TODO: Remove this check when owner-context is removed
|
|
599
|
+
*/
|
|
600
|
+
_warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
|
|
601
|
+
var ownerKeys = Object.keys(ownerBasedContext).sort();
|
|
602
|
+
var parentKeys = Object.keys(parentBasedContext).sort();
|
|
603
|
+
var displayName = this._instance.constructor.displayName || 'ReactCompositeComponent';
|
|
604
|
+
if (ownerKeys.length !== parentKeys.length ||
|
|
605
|
+
ownerKeys.toString() !== parentKeys.toString()) {
|
|
606
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
607
|
+
ownerKeys.length === parentKeys.length &&
|
|
608
|
+
ownerKeys.toString() === parentKeys.toString(),
|
|
609
|
+
'owner based context (keys: %s) does not equal parent based ' +
|
|
610
|
+
'context (keys: %s) while mounting %s ' +
|
|
611
|
+
'(see: http://fb.me/react-context-by-parent)',
|
|
612
|
+
Object.keys(ownerBasedContext),
|
|
613
|
+
Object.keys(parentBasedContext),
|
|
614
|
+
displayName
|
|
615
|
+
) : null);
|
|
616
|
+
} else {
|
|
617
|
+
for (var i = 0; i < parentKeys.length; i++) {
|
|
618
|
+
var key = parentKeys[i];
|
|
619
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
620
|
+
ownerBasedContext[key] === parentBasedContext[key],
|
|
621
|
+
'owner-based and parent-based contexts differ ' +
|
|
622
|
+
'(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
|
|
623
|
+
'(see: http://fb.me/react-context-by-parent)',
|
|
624
|
+
ownerBasedContext[key],
|
|
625
|
+
parentBasedContext[key],
|
|
626
|
+
key,
|
|
627
|
+
displayName
|
|
628
|
+
) : null);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Perform an update to a mounted component. The componentWillReceiveProps and
|
|
635
|
+
* shouldComponentUpdate methods are called, then (assuming the update isn't
|
|
636
|
+
* skipped) the remaining update lifecycle methods are called and the DOM
|
|
637
|
+
* representation is updated.
|
|
638
|
+
*
|
|
639
|
+
* By default, this implements React's rendering and reconciliation algorithm.
|
|
640
|
+
* Sophisticated clients may wish to override this.
|
|
641
|
+
*
|
|
642
|
+
* @param {ReactReconcileTransaction} transaction
|
|
643
|
+
* @param {ReactElement} prevParentElement
|
|
644
|
+
* @param {ReactElement} nextParentElement
|
|
645
|
+
* @internal
|
|
646
|
+
* @overridable
|
|
647
|
+
*/
|
|
648
|
+
updateComponent: function(
|
|
649
|
+
transaction,
|
|
650
|
+
prevParentElement,
|
|
651
|
+
nextParentElement,
|
|
652
|
+
prevUnmaskedContext,
|
|
653
|
+
nextUnmaskedContext
|
|
654
|
+
) {
|
|
655
|
+
// Update refs regardless of what shouldComponentUpdate returns
|
|
656
|
+
ReactComponent.Mixin.updateComponent.call(
|
|
657
|
+
this,
|
|
658
|
+
transaction,
|
|
659
|
+
prevParentElement,
|
|
660
|
+
nextParentElement,
|
|
661
|
+
prevUnmaskedContext,
|
|
662
|
+
nextUnmaskedContext
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
var inst = this._instance;
|
|
666
|
+
|
|
667
|
+
var prevContext = inst.context;
|
|
668
|
+
var prevProps = inst.props;
|
|
669
|
+
var nextContext = prevContext;
|
|
670
|
+
var nextProps = prevProps;
|
|
671
|
+
// Distinguish between a props update versus a simple state update
|
|
672
|
+
if (prevParentElement !== nextParentElement) {
|
|
673
|
+
nextContext = this._processContext(nextParentElement._context);
|
|
674
|
+
nextProps = this._processProps(nextParentElement.props);
|
|
1044
675
|
|
|
1045
676
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
|
1046
|
-
if (
|
|
1047
|
-
|
|
677
|
+
if (inst.componentWillReceiveProps) {
|
|
678
|
+
inst.componentWillReceiveProps(nextProps, nextContext);
|
|
1048
679
|
}
|
|
1049
680
|
}
|
|
1050
681
|
|
|
1051
682
|
this._compositeLifeCycleState = null;
|
|
1052
683
|
|
|
1053
|
-
var nextState = this._pendingState ||
|
|
684
|
+
var nextState = this._pendingState || inst.state;
|
|
1054
685
|
this._pendingState = null;
|
|
1055
686
|
|
|
1056
687
|
var shouldUpdate =
|
|
1057
688
|
this._pendingForceUpdate ||
|
|
1058
|
-
!
|
|
1059
|
-
|
|
689
|
+
!inst.shouldComponentUpdate ||
|
|
690
|
+
inst.shouldComponentUpdate(nextProps, nextState, nextContext);
|
|
1060
691
|
|
|
1061
692
|
if ("production" !== process.env.NODE_ENV) {
|
|
1062
693
|
if (typeof shouldUpdate === "undefined") {
|
|
1063
694
|
console.warn(
|
|
1064
|
-
(
|
|
695
|
+
(inst.constructor.displayName || 'ReactCompositeComponent') +
|
|
1065
696
|
'.shouldComponentUpdate(): Returned undefined instead of a ' +
|
|
1066
697
|
'boolean value. Make sure to return true or false.'
|
|
1067
698
|
);
|
|
1068
699
|
}
|
|
1069
700
|
}
|
|
1070
701
|
|
|
1071
|
-
if (shouldUpdate) {
|
|
1072
|
-
this._pendingForceUpdate = false;
|
|
1073
|
-
// Will set `this.props`, `this.state` and `this.context`.
|
|
1074
|
-
this._performComponentUpdate(
|
|
1075
|
-
nextElement,
|
|
1076
|
-
nextProps,
|
|
1077
|
-
nextState,
|
|
1078
|
-
nextContext,
|
|
1079
|
-
transaction
|
|
1080
|
-
);
|
|
1081
|
-
} else {
|
|
702
|
+
if (!shouldUpdate) {
|
|
1082
703
|
// If it's determined that a component should not update, we still want
|
|
1083
|
-
// to set props and state.
|
|
1084
|
-
this._currentElement =
|
|
1085
|
-
this.
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
// it. TODO: Remove this._owner completely.
|
|
1091
|
-
this._owner = nextElement._owner;
|
|
704
|
+
// to set props and state but we shortcut the rest of the update.
|
|
705
|
+
this._currentElement = nextParentElement;
|
|
706
|
+
this._context = nextUnmaskedContext;
|
|
707
|
+
inst.props = nextProps;
|
|
708
|
+
inst.state = nextState;
|
|
709
|
+
inst.context = nextContext;
|
|
710
|
+
return;
|
|
1092
711
|
}
|
|
712
|
+
|
|
713
|
+
this._pendingForceUpdate = false;
|
|
714
|
+
// Will set `this.props`, `this.state` and `this.context`.
|
|
715
|
+
this._performComponentUpdate(
|
|
716
|
+
nextParentElement,
|
|
717
|
+
nextProps,
|
|
718
|
+
nextState,
|
|
719
|
+
nextContext,
|
|
720
|
+
transaction,
|
|
721
|
+
nextUnmaskedContext
|
|
722
|
+
);
|
|
1093
723
|
},
|
|
1094
724
|
|
|
1095
725
|
/**
|
|
@@ -1101,6 +731,7 @@ var ReactCompositeComponentMixin = {
|
|
|
1101
731
|
* @param {?object} nextState Next object to set as state.
|
|
1102
732
|
* @param {?object} nextContext Next public object to set as context.
|
|
1103
733
|
* @param {ReactReconcileTransaction} transaction
|
|
734
|
+
* @param {?object} unmaskedContext
|
|
1104
735
|
* @private
|
|
1105
736
|
*/
|
|
1106
737
|
_performComponentUpdate: function(
|
|
@@ -1108,329 +739,280 @@ var ReactCompositeComponentMixin = {
|
|
|
1108
739
|
nextProps,
|
|
1109
740
|
nextState,
|
|
1110
741
|
nextContext,
|
|
1111
|
-
transaction
|
|
742
|
+
transaction,
|
|
743
|
+
unmaskedContext
|
|
1112
744
|
) {
|
|
1113
|
-
var
|
|
1114
|
-
|
|
1115
|
-
var
|
|
1116
|
-
var
|
|
745
|
+
var inst = this._instance;
|
|
746
|
+
|
|
747
|
+
var prevProps = inst.props;
|
|
748
|
+
var prevState = inst.state;
|
|
749
|
+
var prevContext = inst.context;
|
|
1117
750
|
|
|
1118
|
-
if (
|
|
1119
|
-
|
|
751
|
+
if (inst.componentWillUpdate) {
|
|
752
|
+
inst.componentWillUpdate(nextProps, nextState, nextContext);
|
|
1120
753
|
}
|
|
1121
754
|
|
|
1122
755
|
this._currentElement = nextElement;
|
|
1123
|
-
this.
|
|
1124
|
-
|
|
1125
|
-
|
|
756
|
+
this._context = unmaskedContext;
|
|
757
|
+
inst.props = nextProps;
|
|
758
|
+
inst.state = nextState;
|
|
759
|
+
inst.context = nextContext;
|
|
1126
760
|
|
|
1127
|
-
|
|
1128
|
-
// it. TODO: Remove this._owner completely.
|
|
1129
|
-
this._owner = nextElement._owner;
|
|
761
|
+
this._updateRenderedComponent(transaction, nextContext);
|
|
1130
762
|
|
|
1131
|
-
|
|
1132
|
-
transaction,
|
|
1133
|
-
prevElement
|
|
1134
|
-
);
|
|
1135
|
-
|
|
1136
|
-
if (this.componentDidUpdate) {
|
|
763
|
+
if (inst.componentDidUpdate) {
|
|
1137
764
|
transaction.getReactMountReady().enqueue(
|
|
1138
|
-
|
|
1139
|
-
|
|
765
|
+
inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext),
|
|
766
|
+
inst
|
|
1140
767
|
);
|
|
1141
768
|
}
|
|
1142
769
|
},
|
|
1143
770
|
|
|
1144
|
-
receiveComponent: function(nextElement, transaction) {
|
|
1145
|
-
if (nextElement === this._currentElement &&
|
|
1146
|
-
nextElement._owner != null) {
|
|
1147
|
-
// Since elements are immutable after the owner is rendered,
|
|
1148
|
-
// we can do a cheap identity compare here to determine if this is a
|
|
1149
|
-
// superfluous reconcile. It's possible for state to be mutable but such
|
|
1150
|
-
// change should trigger an update of the owner which would recreate
|
|
1151
|
-
// the element. We explicitly check for the existence of an owner since
|
|
1152
|
-
// it's possible for a element created outside a composite to be
|
|
1153
|
-
// deeply mutated and reused.
|
|
1154
|
-
return;
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
ReactComponent.Mixin.receiveComponent.call(
|
|
1158
|
-
this,
|
|
1159
|
-
nextElement,
|
|
1160
|
-
transaction
|
|
1161
|
-
);
|
|
1162
|
-
},
|
|
1163
|
-
|
|
1164
771
|
/**
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
* By default, this implements React's rendering and reconciliation algorithm.
|
|
1168
|
-
* Sophisticated clients may wish to override this.
|
|
772
|
+
* Call the component's `render` method and update the DOM accordingly.
|
|
1169
773
|
*
|
|
1170
774
|
* @param {ReactReconcileTransaction} transaction
|
|
1171
|
-
* @param {ReactElement} prevElement
|
|
1172
775
|
* @internal
|
|
1173
|
-
* @overridable
|
|
1174
776
|
*/
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
777
|
+
_updateRenderedComponent: function(transaction, context) {
|
|
778
|
+
var prevComponentInstance = this._renderedComponent;
|
|
779
|
+
var prevRenderedElement = prevComponentInstance._currentElement;
|
|
780
|
+
var nextRenderedElement = this._renderValidatedComponent();
|
|
781
|
+
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
|
|
782
|
+
prevComponentInstance.receiveComponent(
|
|
783
|
+
nextRenderedElement,
|
|
1181
784
|
transaction,
|
|
1182
|
-
|
|
785
|
+
this._processChildContext(context)
|
|
786
|
+
);
|
|
787
|
+
} else {
|
|
788
|
+
// These two IDs are actually the same! But nothing should rely on that.
|
|
789
|
+
var thisID = this._rootNodeID;
|
|
790
|
+
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
791
|
+
prevComponentInstance.unmountComponent();
|
|
792
|
+
|
|
793
|
+
this._renderedComponent = this._instantiateReactComponent(
|
|
794
|
+
nextRenderedElement,
|
|
795
|
+
this._currentElement.type
|
|
796
|
+
);
|
|
797
|
+
var nextMarkup = this._renderedComponent.mountComponent(
|
|
798
|
+
thisID,
|
|
799
|
+
transaction,
|
|
800
|
+
context
|
|
801
|
+
);
|
|
802
|
+
ReactComponentEnvironment.replaceNodeWithMarkupByID(
|
|
803
|
+
prevComponentID,
|
|
804
|
+
nextMarkup
|
|
1183
805
|
);
|
|
1184
|
-
|
|
1185
|
-
var prevComponentInstance = this._renderedComponent;
|
|
1186
|
-
var prevElement = prevComponentInstance._currentElement;
|
|
1187
|
-
var nextElement = this._renderValidatedComponent();
|
|
1188
|
-
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
|
1189
|
-
prevComponentInstance.receiveComponent(nextElement, transaction);
|
|
1190
|
-
} else {
|
|
1191
|
-
// These two IDs are actually the same! But nothing should rely on that.
|
|
1192
|
-
var thisID = this._rootNodeID;
|
|
1193
|
-
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
1194
|
-
prevComponentInstance.unmountComponent();
|
|
1195
|
-
this._renderedComponent = instantiateReactComponent(
|
|
1196
|
-
nextElement,
|
|
1197
|
-
this._currentElement.type
|
|
1198
|
-
);
|
|
1199
|
-
var nextMarkup = this._renderedComponent.mountComponent(
|
|
1200
|
-
thisID,
|
|
1201
|
-
transaction,
|
|
1202
|
-
this._mountDepth + 1
|
|
1203
|
-
);
|
|
1204
|
-
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
|
|
1205
|
-
prevComponentID,
|
|
1206
|
-
nextMarkup
|
|
1207
|
-
);
|
|
1208
|
-
}
|
|
1209
806
|
}
|
|
1210
|
-
|
|
807
|
+
},
|
|
1211
808
|
|
|
1212
809
|
/**
|
|
1213
|
-
*
|
|
1214
|
-
* certainty that we are **not** in a DOM transaction.
|
|
1215
|
-
*
|
|
1216
|
-
* You may want to call this when you know that some deeper aspect of the
|
|
1217
|
-
* component's state has changed but `setState` was not called.
|
|
1218
|
-
*
|
|
1219
|
-
* This will not invoke `shouldUpdateComponent`, but it will invoke
|
|
1220
|
-
* `componentWillUpdate` and `componentDidUpdate`.
|
|
1221
|
-
*
|
|
1222
|
-
* @param {?function} callback Called after update is complete.
|
|
1223
|
-
* @final
|
|
1224
|
-
* @protected
|
|
810
|
+
* @private
|
|
1225
811
|
*/
|
|
1226
|
-
|
|
1227
|
-
var
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
|
|
1241
|
-
ReactCurrentOwner.current == null));
|
|
1242
|
-
this._pendingForceUpdate = true;
|
|
1243
|
-
ReactUpdates.enqueueUpdate(this, callback);
|
|
812
|
+
_renderValidatedComponentWithoutOwnerOrContext: function() {
|
|
813
|
+
var inst = this._instance;
|
|
814
|
+
var renderedComponent = inst.render();
|
|
815
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
816
|
+
// We allow auto-mocks to proceed as if they're returning null.
|
|
817
|
+
if (typeof renderedComponent === 'undefined' &&
|
|
818
|
+
inst.render._isMockFunction) {
|
|
819
|
+
// This is probably bad practice. Consider warning here and
|
|
820
|
+
// deprecating this convenience.
|
|
821
|
+
renderedComponent = null;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
return renderedComponent;
|
|
1244
826
|
},
|
|
1245
827
|
|
|
1246
828
|
/**
|
|
1247
829
|
* @private
|
|
1248
830
|
*/
|
|
1249
|
-
_renderValidatedComponent:
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
|
|
1264
|
-
} else {
|
|
1265
|
-
ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
|
|
1266
|
-
}
|
|
1267
|
-
} finally {
|
|
1268
|
-
ReactContext.current = previousContext;
|
|
1269
|
-
ReactCurrentOwner.current = null;
|
|
1270
|
-
}
|
|
1271
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
1272
|
-
ReactElement.isValidElement(renderedComponent),
|
|
1273
|
-
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
1274
|
-
'returned undefined, an array or some other invalid object.',
|
|
1275
|
-
this.constructor.displayName || 'ReactCompositeComponent'
|
|
1276
|
-
) : invariant(ReactElement.isValidElement(renderedComponent)));
|
|
1277
|
-
return renderedComponent;
|
|
831
|
+
_renderValidatedComponent: function() {
|
|
832
|
+
var renderedComponent;
|
|
833
|
+
var previousContext = ReactContext.current;
|
|
834
|
+
ReactContext.current = this._processChildContext(
|
|
835
|
+
this._currentElement._context
|
|
836
|
+
);
|
|
837
|
+
ReactCurrentOwner.current = this;
|
|
838
|
+
var inst = this._instance;
|
|
839
|
+
try {
|
|
840
|
+
renderedComponent =
|
|
841
|
+
this._renderValidatedComponentWithoutOwnerOrContext();
|
|
842
|
+
} finally {
|
|
843
|
+
ReactContext.current = previousContext;
|
|
844
|
+
ReactCurrentOwner.current = null;
|
|
1278
845
|
}
|
|
1279
|
-
|
|
846
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
847
|
+
// TODO: An `isValidNode` function would probably be more appropriate
|
|
848
|
+
renderedComponent === null || renderedComponent === false ||
|
|
849
|
+
ReactElement.isValidElement(renderedComponent),
|
|
850
|
+
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
851
|
+
'returned undefined, an array or some other invalid object.',
|
|
852
|
+
inst.constructor.displayName || 'ReactCompositeComponent'
|
|
853
|
+
) : invariant(// TODO: An `isValidNode` function would probably be more appropriate
|
|
854
|
+
renderedComponent === null || renderedComponent === false ||
|
|
855
|
+
ReactElement.isValidElement(renderedComponent)));
|
|
856
|
+
return renderedComponent;
|
|
857
|
+
},
|
|
1280
858
|
|
|
1281
859
|
/**
|
|
860
|
+
* Lazily allocates the refs object and stores `component` as `ref`.
|
|
861
|
+
*
|
|
862
|
+
* @param {string} ref Reference name.
|
|
863
|
+
* @param {component} component Component to store as `ref`.
|
|
864
|
+
* @final
|
|
1282
865
|
* @private
|
|
1283
866
|
*/
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
}
|
|
1289
|
-
var method = this.__reactAutoBindMap[autoBindKey];
|
|
1290
|
-
this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard(
|
|
1291
|
-
method,
|
|
1292
|
-
this.constructor.displayName + '.' + autoBindKey
|
|
1293
|
-
));
|
|
1294
|
-
}
|
|
867
|
+
attachRef: function(ref, component) {
|
|
868
|
+
var inst = this.getPublicInstance();
|
|
869
|
+
var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
|
|
870
|
+
refs[ref] = component.getPublicInstance();
|
|
1295
871
|
},
|
|
1296
872
|
|
|
1297
873
|
/**
|
|
1298
|
-
*
|
|
874
|
+
* Detaches a reference name.
|
|
1299
875
|
*
|
|
1300
|
-
* @param {
|
|
876
|
+
* @param {string} ref Name to dereference.
|
|
877
|
+
* @final
|
|
1301
878
|
* @private
|
|
1302
879
|
*/
|
|
1303
|
-
|
|
1304
|
-
var
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
boundMethod.__reactBoundContext = component;
|
|
1308
|
-
boundMethod.__reactBoundMethod = method;
|
|
1309
|
-
boundMethod.__reactBoundArguments = null;
|
|
1310
|
-
var componentName = component.constructor.displayName;
|
|
1311
|
-
var _bind = boundMethod.bind;
|
|
1312
|
-
boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
|
|
1313
|
-
// User is trying to bind() an autobound method; we effectively will
|
|
1314
|
-
// ignore the value of "this" that the user is trying to use, so
|
|
1315
|
-
// let's warn.
|
|
1316
|
-
if (newThis !== component && newThis !== null) {
|
|
1317
|
-
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
1318
|
-
console.warn(
|
|
1319
|
-
'bind(): React component methods may only be bound to the ' +
|
|
1320
|
-
'component instance. See ' + componentName
|
|
1321
|
-
);
|
|
1322
|
-
} else if (!args.length) {
|
|
1323
|
-
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
1324
|
-
console.warn(
|
|
1325
|
-
'bind(): You are binding a component method to the component. ' +
|
|
1326
|
-
'React does this for you automatically in a high-performance ' +
|
|
1327
|
-
'way, so you can safely remove this call. See ' + componentName
|
|
1328
|
-
);
|
|
1329
|
-
return boundMethod;
|
|
1330
|
-
}
|
|
1331
|
-
var reboundMethod = _bind.apply(boundMethod, arguments);
|
|
1332
|
-
reboundMethod.__reactBoundContext = component;
|
|
1333
|
-
reboundMethod.__reactBoundMethod = method;
|
|
1334
|
-
reboundMethod.__reactBoundArguments = args;
|
|
1335
|
-
return reboundMethod;
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
return boundMethod;
|
|
1339
|
-
}
|
|
1340
|
-
};
|
|
880
|
+
detachRef: function(ref) {
|
|
881
|
+
var refs = this.getPublicInstance().refs;
|
|
882
|
+
delete refs[ref];
|
|
883
|
+
},
|
|
1341
884
|
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
885
|
+
/**
|
|
886
|
+
* Get the publicly accessible representation of this component - i.e. what
|
|
887
|
+
* is exposed by refs and returned by React.render. Can be null for stateless
|
|
888
|
+
* components.
|
|
889
|
+
*
|
|
890
|
+
* @return {ReactComponent} the public component instance.
|
|
891
|
+
* @internal
|
|
892
|
+
*/
|
|
893
|
+
getPublicInstance: function() {
|
|
894
|
+
return this._instance;
|
|
895
|
+
},
|
|
1350
896
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
*
|
|
1354
|
-
* @class ReactCompositeComponent
|
|
1355
|
-
* @extends ReactComponent
|
|
1356
|
-
* @extends ReactOwner
|
|
1357
|
-
* @extends ReactPropTransferer
|
|
1358
|
-
*/
|
|
1359
|
-
var ReactCompositeComponent = {
|
|
897
|
+
// Stub
|
|
898
|
+
_instantiateReactComponent: null
|
|
1360
899
|
|
|
1361
|
-
|
|
900
|
+
});
|
|
1362
901
|
|
|
1363
|
-
|
|
902
|
+
var ShallowMixin = assign({},
|
|
903
|
+
ReactCompositeComponentMixin, {
|
|
1364
904
|
|
|
1365
905
|
/**
|
|
1366
|
-
*
|
|
906
|
+
* Initializes the component, renders markup, and registers event listeners.
|
|
1367
907
|
*
|
|
1368
|
-
* @param {
|
|
1369
|
-
* @
|
|
1370
|
-
* @
|
|
908
|
+
* @param {string} rootID DOM ID of the root node.
|
|
909
|
+
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
910
|
+
* @return {ReactElement} Shallow rendering of the component.
|
|
911
|
+
* @final
|
|
912
|
+
* @internal
|
|
1371
913
|
*/
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
Constructor.prototype = new ReactCompositeComponentBase();
|
|
1379
|
-
Constructor.prototype.constructor = Constructor;
|
|
1380
|
-
|
|
1381
|
-
injectedMixins.forEach(
|
|
1382
|
-
mixSpecIntoComponent.bind(null, Constructor)
|
|
914
|
+
mountComponent: function(rootID, transaction, context) {
|
|
915
|
+
ReactComponent.Mixin.mountComponent.call(
|
|
916
|
+
this,
|
|
917
|
+
rootID,
|
|
918
|
+
transaction,
|
|
919
|
+
context
|
|
1383
920
|
);
|
|
1384
921
|
|
|
1385
|
-
|
|
922
|
+
var inst = this._instance;
|
|
1386
923
|
|
|
1387
|
-
//
|
|
1388
|
-
|
|
1389
|
-
Constructor.defaultProps = Constructor.getDefaultProps();
|
|
1390
|
-
}
|
|
924
|
+
// Store a reference from the instance back to the internal representation
|
|
925
|
+
ReactInstanceMap.set(inst, this);
|
|
1391
926
|
|
|
1392
|
-
|
|
1393
|
-
Constructor.prototype.render,
|
|
1394
|
-
'createClass(...): Class specification must implement a `render` method.'
|
|
1395
|
-
) : invariant(Constructor.prototype.render));
|
|
927
|
+
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
1396
928
|
|
|
929
|
+
// No context for shallow-mounted components.
|
|
930
|
+
inst.props = this._processProps(this._currentElement.props);
|
|
931
|
+
|
|
932
|
+
var initialState = inst.getInitialState ? inst.getInitialState() : null;
|
|
1397
933
|
if ("production" !== process.env.NODE_ENV) {
|
|
1398
|
-
if
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
(spec.displayName || 'A component') + ' has a method called ' +
|
|
1405
|
-
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
|
|
1406
|
-
'The name is phrased as a question because the function is ' +
|
|
1407
|
-
'expected to return a value.'
|
|
1408
|
-
);
|
|
934
|
+
// We allow auto-mocks to proceed as if they're returning null.
|
|
935
|
+
if (typeof initialState === 'undefined' &&
|
|
936
|
+
inst.getInitialState._isMockFunction) {
|
|
937
|
+
// This is probably bad practice. Consider warning here and
|
|
938
|
+
// deprecating this convenience.
|
|
939
|
+
initialState = null;
|
|
1409
940
|
}
|
|
1410
941
|
}
|
|
942
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
943
|
+
typeof initialState === 'object' && !Array.isArray(initialState),
|
|
944
|
+
'%s.getInitialState(): must return an object or null',
|
|
945
|
+
inst.constructor.displayName || 'ReactCompositeComponent'
|
|
946
|
+
) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
|
|
947
|
+
inst.state = initialState;
|
|
1411
948
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
949
|
+
this._pendingState = null;
|
|
950
|
+
this._pendingForceUpdate = false;
|
|
951
|
+
|
|
952
|
+
if (inst.componentWillMount) {
|
|
953
|
+
inst.componentWillMount();
|
|
954
|
+
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
955
|
+
// `this._pendingState` without triggering a re-render.
|
|
956
|
+
if (this._pendingState) {
|
|
957
|
+
inst.state = this._pendingState;
|
|
958
|
+
this._pendingState = null;
|
|
1416
959
|
}
|
|
1417
960
|
}
|
|
1418
961
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
962
|
+
// No recursive call to instantiateReactComponent for shallow rendering.
|
|
963
|
+
this._renderedComponent =
|
|
964
|
+
this._renderValidatedComponentWithoutOwnerOrContext();
|
|
965
|
+
|
|
966
|
+
// Done with mounting, `setState` will now trigger UI changes.
|
|
967
|
+
this._compositeLifeCycleState = null;
|
|
968
|
+
|
|
969
|
+
// No call to this._renderedComponent.mountComponent for shallow
|
|
970
|
+
// rendering.
|
|
971
|
+
|
|
972
|
+
if (inst.componentDidMount) {
|
|
973
|
+
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
|
|
1423
974
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
);
|
|
975
|
+
|
|
976
|
+
return this._renderedComponent;
|
|
1427
977
|
},
|
|
1428
978
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
979
|
+
/**
|
|
980
|
+
* Call the component's `render` method and update the DOM accordingly.
|
|
981
|
+
*
|
|
982
|
+
* @param {ReactReconcileTransaction} transaction
|
|
983
|
+
* @internal
|
|
984
|
+
*/
|
|
985
|
+
_updateRenderedComponent: function(transaction) {
|
|
986
|
+
var prevComponentInstance = this._renderedComponent;
|
|
987
|
+
var prevRenderedElement = prevComponentInstance._currentElement;
|
|
988
|
+
// Use the without-owner-or-context variant of _rVC below:
|
|
989
|
+
var nextRenderedElement =
|
|
990
|
+
this._renderValidatedComponentWithoutOwnerOrContext();
|
|
991
|
+
// This is a noop in shallow render
|
|
992
|
+
shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement);
|
|
993
|
+
this._renderedComponent = nextRenderedElement;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
ReactPerf.measureMethods(
|
|
999
|
+
ReactCompositeComponentMixin,
|
|
1000
|
+
'ReactCompositeComponent',
|
|
1001
|
+
{
|
|
1002
|
+
mountComponent: 'mountComponent',
|
|
1003
|
+
updateComponent: 'updateComponent',
|
|
1004
|
+
_renderValidatedComponent: '_renderValidatedComponent'
|
|
1433
1005
|
}
|
|
1006
|
+
);
|
|
1007
|
+
|
|
1008
|
+
var ReactCompositeComponent = {
|
|
1009
|
+
|
|
1010
|
+
LifeCycle: CompositeLifeCycle,
|
|
1011
|
+
|
|
1012
|
+
Mixin: ReactCompositeComponentMixin,
|
|
1013
|
+
|
|
1014
|
+
ShallowMixin: ShallowMixin
|
|
1015
|
+
|
|
1434
1016
|
};
|
|
1435
1017
|
|
|
1436
1018
|
module.exports = ReactCompositeComponent;
|