react 0.12.2 → 0.13.0-beta.2
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 +986 -511
- package/dist/react-with-addons.js +6076 -4560
- package/dist/react-with-addons.min.js +6 -7
- package/dist/react.js +5386 -4170
- package/dist/react.min.js +6 -7
- package/lib/AutoFocusMixin.js +2 -2
- package/lib/BeforeInputEventPlugin.js +388 -115
- package/lib/CSSCore.js +1 -1
- package/lib/CSSProperty.js +2 -2
- package/lib/CSSPropertyOperations.js +58 -11
- package/lib/CallbackQueue.js +3 -3
- package/lib/ChangeEventPlugin.js +4 -4
- package/lib/ClientReactRootIndex.js +2 -2
- package/lib/DOMChildrenOperations.js +10 -47
- package/lib/DOMProperty.js +2 -2
- package/lib/DOMPropertyOperations.js +11 -16
- package/lib/Danger.js +8 -7
- package/lib/DefaultEventPluginOrder.js +3 -4
- package/lib/EnterLeaveEventPlugin.js +2 -2
- package/lib/EventConstants.js +2 -2
- package/lib/EventListener.js +1 -1
- package/lib/EventPluginHub.js +10 -8
- package/lib/EventPluginRegistry.js +2 -2
- package/lib/EventPluginUtils.js +4 -4
- package/lib/EventPropagators.js +2 -2
- package/lib/ExecutionEnvironment.js +3 -4
- package/lib/FallbackCompositionState.js +89 -0
- package/lib/HTMLDOMPropertyConfig.js +23 -10
- package/lib/LinkedStateMixin.js +2 -2
- package/lib/LinkedValueUtils.js +4 -4
- package/lib/LocalEventTrapMixin.js +10 -3
- package/lib/MobileSafariClickEventPlugin.js +2 -2
- package/lib/Object.assign.js +4 -2
- package/lib/PooledClass.js +2 -2
- package/lib/React.js +19 -58
- package/lib/ReactBrowserComponentMixin.js +4 -14
- package/lib/ReactBrowserEventEmitter.js +6 -8
- package/lib/ReactCSSTransitionGroup.js +5 -2
- package/lib/ReactCSSTransitionGroupChild.js +20 -7
- package/lib/ReactChildReconciler.js +125 -0
- package/lib/ReactChildren.js +13 -10
- package/lib/ReactClass.js +918 -0
- package/lib/ReactComponent.js +98 -406
- package/lib/ReactComponentBrowserEnvironment.js +11 -84
- package/lib/ReactComponentEnvironment.js +57 -0
- package/lib/ReactComponentWithPureRenderMixin.js +2 -2
- package/lib/ReactCompositeComponent.js +574 -1140
- package/lib/ReactContext.js +17 -3
- package/lib/ReactCurrentOwner.js +2 -2
- package/lib/ReactDOM.js +4 -9
- package/lib/ReactDOMButton.js +6 -7
- package/lib/ReactDOMComponent.js +123 -105
- package/lib/ReactDOMForm.js +6 -7
- package/lib/ReactDOMIDOperations.js +59 -77
- package/lib/ReactDOMIframe.js +43 -0
- package/lib/ReactDOMImg.js +5 -7
- package/lib/ReactDOMInput.js +6 -7
- package/lib/ReactDOMOption.js +6 -7
- package/lib/ReactDOMSelect.js +58 -66
- package/lib/ReactDOMSelection.js +7 -3
- package/lib/{ReactTextComponent.js → ReactDOMTextComponent.js} +48 -37
- package/lib/ReactDOMTextarea.js +6 -7
- package/lib/ReactDefaultBatchingStrategy.js +5 -5
- package/lib/ReactDefaultInjection.js +39 -9
- package/lib/ReactDefaultPerf.js +17 -8
- package/lib/ReactDefaultPerfAnalysis.js +2 -2
- package/lib/ReactElement.js +23 -15
- package/lib/ReactElementValidator.js +206 -89
- package/lib/ReactEmptyComponent.js +33 -15
- package/lib/ReactErrorUtils.js +1 -1
- package/lib/ReactEventEmitterMixin.js +2 -2
- package/lib/ReactEventListener.js +4 -5
- package/lib/ReactFragment.js +172 -0
- package/lib/ReactInjection.js +8 -6
- package/lib/ReactInputSelection.js +4 -5
- package/lib/ReactInstanceHandles.js +4 -3
- package/lib/ReactInstanceMap.js +47 -0
- package/lib/ReactLifeCycle.js +35 -0
- package/lib/ReactLink.js +2 -2
- package/lib/ReactMarkupChecksum.js +2 -2
- package/lib/ReactMount.js +264 -71
- package/lib/ReactMultiChild.js +50 -48
- package/lib/ReactMultiChildUpdateTypes.js +2 -2
- package/lib/ReactNativeComponent.js +59 -25
- package/lib/ReactOwner.js +5 -49
- package/lib/ReactPerf.js +22 -2
- package/lib/ReactPropTransferer.js +3 -58
- package/lib/ReactPropTypeLocationNames.js +2 -2
- package/lib/ReactPropTypeLocations.js +2 -2
- package/lib/ReactPropTypes.js +17 -25
- package/lib/ReactPutListenerQueue.js +2 -2
- package/lib/ReactReconcileTransaction.js +2 -2
- package/lib/ReactReconciler.js +121 -0
- package/lib/ReactRef.js +69 -0
- package/lib/ReactRootIndex.js +2 -2
- package/lib/ReactServerRendering.js +6 -4
- package/lib/ReactServerRenderingTransaction.js +2 -2
- package/lib/ReactStateSetters.js +2 -2
- package/lib/ReactTestUtils.js +113 -27
- package/lib/ReactTransitionChildMapping.js +8 -4
- package/lib/ReactTransitionEvents.js +2 -2
- package/lib/ReactTransitionGroup.js +53 -12
- package/lib/ReactUpdateQueue.js +295 -0
- package/lib/ReactUpdates.js +54 -62
- package/lib/ReactWithAddons.js +4 -2
- package/lib/SVGDOMPropertyConfig.js +2 -2
- package/lib/SelectEventPlugin.js +4 -4
- package/lib/ServerReactRootIndex.js +2 -2
- package/lib/SimpleEventPlugin.js +4 -4
- package/lib/SyntheticClipboardEvent.js +2 -3
- package/lib/SyntheticCompositionEvent.js +2 -3
- package/lib/SyntheticDragEvent.js +2 -2
- package/lib/SyntheticEvent.js +12 -4
- package/lib/SyntheticFocusEvent.js +2 -2
- package/lib/SyntheticInputEvent.js +2 -3
- package/lib/SyntheticKeyboardEvent.js +2 -2
- package/lib/SyntheticMouseEvent.js +3 -5
- package/lib/SyntheticTouchEvent.js +2 -2
- package/lib/SyntheticUIEvent.js +2 -2
- package/lib/SyntheticWheelEvent.js +2 -2
- package/lib/Transaction.js +4 -4
- package/lib/ViewportMetrics.js +3 -6
- package/lib/accumulateInto.js +2 -2
- package/lib/adler32.js +2 -2
- package/lib/camelize.js +1 -1
- package/lib/camelizeStyleName.js +1 -1
- package/lib/cloneWithProps.js +4 -4
- package/lib/containsNode.js +1 -1
- package/lib/{createArrayFrom.js → createArrayFromMixed.js} +6 -6
- package/lib/createFullPageComponent.js +4 -4
- package/lib/createNodesFromMarkup.js +4 -4
- package/lib/cx.js +1 -1
- package/lib/dangerousStyleValue.js +2 -2
- package/lib/emptyFunction.js +1 -1
- package/lib/emptyObject.js +1 -1
- package/lib/{escapeTextForBrowser.js → escapeTextContentForBrowser.js} +10 -11
- package/lib/findDOMNode.js +51 -0
- package/lib/flattenChildren.js +12 -23
- package/lib/focusNode.js +1 -1
- package/lib/forEachAccumulated.js +2 -2
- package/lib/getActiveElement.js +1 -1
- package/lib/getEventCharCode.js +2 -2
- package/lib/getEventKey.js +2 -2
- package/lib/getEventModifierState.js +2 -2
- package/lib/getEventTarget.js +2 -2
- package/lib/getIteratorFn.js +42 -0
- package/lib/getMarkupWrap.js +1 -1
- package/lib/getNodeForCharacterOffset.js +3 -3
- package/lib/getReactRootElementInContainer.js +2 -2
- package/lib/getTextContentAccessor.js +2 -2
- package/lib/getUnboundedScrollPosition.js +1 -1
- package/lib/hyphenate.js +1 -1
- package/lib/hyphenateStyleName.js +1 -1
- package/lib/instantiateReactComponent.js +90 -68
- package/lib/invariant.js +1 -1
- package/lib/isEventSupported.js +2 -2
- package/lib/isNode.js +4 -5
- package/lib/isTextInputElement.js +3 -4
- package/lib/isTextNode.js +1 -1
- package/lib/joinClasses.js +2 -2
- package/lib/keyMirror.js +2 -2
- package/lib/keyOf.js +1 -1
- package/lib/mapObject.js +1 -1
- package/lib/memoizeStringOnly.js +5 -6
- package/lib/onlyChild.js +2 -2
- package/lib/performance.js +1 -1
- package/lib/performanceNow.js +1 -1
- package/lib/quoteAttributeValueForBrowser.js +26 -0
- package/lib/setInnerHTML.js +13 -2
- package/lib/setTextContent.js +40 -0
- package/lib/shallowEqual.js +2 -2
- package/lib/shouldUpdateReactComponent.js +71 -7
- package/lib/toArray.js +2 -2
- package/lib/traverseAllChildren.js +114 -56
- package/lib/update.js +2 -2
- package/lib/warning.js +20 -2
- package/package.json +1 -1
- package/lib/CompositionEventPlugin.js +0 -257
- package/lib/ReactLegacyElement.js +0 -243
- package/lib/copyProperties.js +0 -54
- package/lib/deprecated.js +0 -47
- package/lib/merge.js +0 -34
- package/lib/mergeInto.js +0 -24
- package/lib/monitorCodeUse.js +0 -30
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013-
|
|
2
|
+
* Copyright 2013-2015, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the BSD-style license found in the
|
|
@@ -11,31 +11,23 @@
|
|
|
11
11
|
|
|
12
12
|
/*jslint evil: true */
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
'use strict';
|
|
15
15
|
|
|
16
16
|
var ReactDOMIDOperations = require("./ReactDOMIDOperations");
|
|
17
|
-
var ReactMarkupChecksum = require("./ReactMarkupChecksum");
|
|
18
17
|
var ReactMount = require("./ReactMount");
|
|
19
|
-
var ReactPerf = require("./ReactPerf");
|
|
20
|
-
var ReactReconcileTransaction = require("./ReactReconcileTransaction");
|
|
21
|
-
|
|
22
|
-
var getReactRootElementInContainer = require("./getReactRootElementInContainer");
|
|
23
|
-
var invariant = require("./invariant");
|
|
24
|
-
var setInnerHTML = require("./setInnerHTML");
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
var ELEMENT_NODE_TYPE = 1;
|
|
28
|
-
var DOC_NODE_TYPE = 9;
|
|
29
|
-
|
|
30
18
|
|
|
31
19
|
/**
|
|
32
|
-
* Abstracts away all functionality of
|
|
33
|
-
* the browser context.
|
|
20
|
+
* Abstracts away all functionality of the reconciler that requires knowledge of
|
|
21
|
+
* the browser context. TODO: These callers should be refactored to avoid the
|
|
22
|
+
* need for this injection.
|
|
34
23
|
*/
|
|
35
24
|
var ReactComponentBrowserEnvironment = {
|
|
36
|
-
ReactReconcileTransaction: ReactReconcileTransaction,
|
|
37
25
|
|
|
38
|
-
|
|
26
|
+
processChildrenUpdates:
|
|
27
|
+
ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,
|
|
28
|
+
|
|
29
|
+
replaceNodeWithMarkupByID:
|
|
30
|
+
ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,
|
|
39
31
|
|
|
40
32
|
/**
|
|
41
33
|
* If a particular environment requires that some resources be cleaned up,
|
|
@@ -46,73 +38,8 @@ var ReactComponentBrowserEnvironment = {
|
|
|
46
38
|
*/
|
|
47
39
|
unmountIDFromEnvironment: function(rootNodeID) {
|
|
48
40
|
ReactMount.purgeID(rootNodeID);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @param {string} markup Markup string to place into the DOM Element.
|
|
53
|
-
* @param {DOMElement} container DOM Element to insert markup into.
|
|
54
|
-
* @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
|
|
55
|
-
* container if possible.
|
|
56
|
-
*/
|
|
57
|
-
mountImageIntoNode: ReactPerf.measure(
|
|
58
|
-
'ReactComponentBrowserEnvironment',
|
|
59
|
-
'mountImageIntoNode',
|
|
60
|
-
function(markup, container, shouldReuseMarkup) {
|
|
61
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
62
|
-
container && (
|
|
63
|
-
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
64
|
-
container.nodeType === DOC_NODE_TYPE
|
|
65
|
-
),
|
|
66
|
-
'mountComponentIntoNode(...): Target container is not valid.'
|
|
67
|
-
) : invariant(container && (
|
|
68
|
-
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
69
|
-
container.nodeType === DOC_NODE_TYPE
|
|
70
|
-
)));
|
|
71
|
-
|
|
72
|
-
if (shouldReuseMarkup) {
|
|
73
|
-
if (ReactMarkupChecksum.canReuseMarkup(
|
|
74
|
-
markup,
|
|
75
|
-
getReactRootElementInContainer(container))) {
|
|
76
|
-
return;
|
|
77
|
-
} else {
|
|
78
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
79
|
-
container.nodeType !== DOC_NODE_TYPE,
|
|
80
|
-
'You\'re trying to render a component to the document using ' +
|
|
81
|
-
'server rendering but the checksum was invalid. This usually ' +
|
|
82
|
-
'means you rendered a different component type or props on ' +
|
|
83
|
-
'the client from the one on the server, or your render() ' +
|
|
84
|
-
'methods are impure. React cannot handle this case due to ' +
|
|
85
|
-
'cross-browser quirks by rendering at the document root. You ' +
|
|
86
|
-
'should look for environment dependent code in your components ' +
|
|
87
|
-
'and ensure the props are the same client and server side.'
|
|
88
|
-
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
89
|
-
|
|
90
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
91
|
-
console.warn(
|
|
92
|
-
'React attempted to use reuse markup in a container but the ' +
|
|
93
|
-
'checksum was invalid. This generally means that you are ' +
|
|
94
|
-
'using server rendering and the markup generated on the ' +
|
|
95
|
-
'server was not what the client was expecting. React injected ' +
|
|
96
|
-
'new markup to compensate which works but you have lost many ' +
|
|
97
|
-
'of the benefits of server rendering. Instead, figure out ' +
|
|
98
|
-
'why the markup being generated is different on the client ' +
|
|
99
|
-
'or server.'
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
106
|
-
container.nodeType !== DOC_NODE_TYPE,
|
|
107
|
-
'You\'re trying to render a component to the document but ' +
|
|
108
|
-
'you didn\'t use server rendering. We can\'t do this ' +
|
|
109
|
-
'without using server rendering due to cross-browser quirks. ' +
|
|
110
|
-
'See renderComponentToString() for server rendering.'
|
|
111
|
-
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
41
|
+
}
|
|
112
42
|
|
|
113
|
-
setInnerHTML(container, markup);
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
43
|
};
|
|
117
44
|
|
|
118
45
|
module.exports = ReactComponentBrowserEnvironment;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2014-2015, 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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013-
|
|
2
|
+
* Copyright 2013-2015, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the BSD-style license found in the
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @providesModule ReactComponentWithPureRenderMixin
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
'use strict';
|
|
13
13
|
|
|
14
14
|
var shallowEqual = require("./shallowEqual");
|
|
15
15
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013-
|
|
2
|
+
* Copyright 2013-2015, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the BSD-style license found in the
|
|
@@ -9,707 +9,73 @@
|
|
|
9
9
|
* @providesModule ReactCompositeComponent
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
'use strict';
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var ReactComponentEnvironment = require("./ReactComponentEnvironment");
|
|
15
15
|
var ReactContext = require("./ReactContext");
|
|
16
16
|
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
17
17
|
var ReactElement = require("./ReactElement");
|
|
18
18
|
var ReactElementValidator = require("./ReactElementValidator");
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
var ReactOwner = require("./ReactOwner");
|
|
19
|
+
var ReactInstanceMap = require("./ReactInstanceMap");
|
|
20
|
+
var ReactLifeCycle = require("./ReactLifeCycle");
|
|
21
|
+
var ReactNativeComponent = require("./ReactNativeComponent");
|
|
23
22
|
var ReactPerf = require("./ReactPerf");
|
|
24
|
-
var ReactPropTransferer = require("./ReactPropTransferer");
|
|
25
23
|
var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
26
24
|
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
25
|
+
var ReactReconciler = require("./ReactReconciler");
|
|
27
26
|
var ReactUpdates = require("./ReactUpdates");
|
|
28
27
|
|
|
29
28
|
var assign = require("./Object.assign");
|
|
30
|
-
var
|
|
29
|
+
var emptyObject = require("./emptyObject");
|
|
31
30
|
var invariant = require("./invariant");
|
|
32
|
-
var keyMirror = require("./keyMirror");
|
|
33
|
-
var keyOf = require("./keyOf");
|
|
34
|
-
var monitorCodeUse = require("./monitorCodeUse");
|
|
35
|
-
var mapObject = require("./mapObject");
|
|
36
31
|
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
37
32
|
var warning = require("./warning");
|
|
38
33
|
|
|
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
34
|
function getDeclarationErrorAddendum(component) {
|
|
394
|
-
var owner = component._owner || null;
|
|
395
|
-
if (owner
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
return '';
|
|
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'));
|
|
35
|
+
var owner = component._currentElement._owner || null;
|
|
36
|
+
if (owner) {
|
|
37
|
+
var name = owner.getName();
|
|
38
|
+
if (name) {
|
|
39
|
+
return ' Check the render method of `' + name + '`.';
|
|
413
40
|
}
|
|
414
41
|
}
|
|
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
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function validateLifeCycleOnReplaceState(instance) {
|
|
448
|
-
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
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
456
|
-
ReactCurrentOwner.current == null,
|
|
457
|
-
'replaceState(...): Cannot update during an existing state transition ' +
|
|
458
|
-
'(such as within `render`). Render methods should be a pure function ' +
|
|
459
|
-
'of props and state.'
|
|
460
|
-
) : invariant(ReactCurrentOwner.current == null));
|
|
461
|
-
("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
|
|
462
|
-
'replaceState(...): Cannot update while unmounting component. This ' +
|
|
463
|
-
'usually means you called setState() on an unmounted component.'
|
|
464
|
-
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
|
|
465
|
-
}
|
|
466
|
-
|
|
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
|
-
}
|
|
42
|
+
return '';
|
|
604
43
|
}
|
|
605
44
|
|
|
606
45
|
/**
|
|
607
|
-
*
|
|
46
|
+
* ------------------ The Life-Cycle of a Composite Component ------------------
|
|
608
47
|
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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.
|
|
48
|
+
* - constructor: Initialization of state. The instance is now retained.
|
|
49
|
+
* - componentWillMount
|
|
50
|
+
* - render
|
|
51
|
+
* - [children's constructors]
|
|
52
|
+
* - [children's componentWillMount and render]
|
|
53
|
+
* - [children's componentDidMount]
|
|
54
|
+
* - componentDidMount
|
|
636
55
|
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
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.
|
|
56
|
+
* Update Phases:
|
|
57
|
+
* - componentWillReceiveProps (only called if parent updated)
|
|
58
|
+
* - shouldComponentUpdate
|
|
59
|
+
* - componentWillUpdate
|
|
60
|
+
* - render
|
|
61
|
+
* - [children's constructors or receive props phases]
|
|
62
|
+
* - componentDidUpdate
|
|
657
63
|
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
*
|
|
64
|
+
* - componentWillUnmount
|
|
65
|
+
* - [children's componentWillUnmount]
|
|
66
|
+
* - [children destroyed]
|
|
67
|
+
* - (destroyed): The instance is now blank, released by React and ready for GC.
|
|
68
|
+
*
|
|
69
|
+
* -----------------------------------------------------------------------------
|
|
662
70
|
*/
|
|
663
|
-
function createChainedFunction(one, two) {
|
|
664
|
-
return function chainedFunction() {
|
|
665
|
-
one.apply(this, arguments);
|
|
666
|
-
two.apply(this, arguments);
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
71
|
|
|
670
72
|
/**
|
|
671
|
-
*
|
|
672
|
-
* `
|
|
73
|
+
* An incrementing ID assigned to each component when it is mounted. This is
|
|
74
|
+
* used to enforce the order in which `ReactUpdates` updates dirty components.
|
|
673
75
|
*
|
|
674
|
-
*
|
|
675
|
-
* `this._lifeCycleState`. The following diagram shows how the states overlap in
|
|
676
|
-
* time. There are times when the CompositeLifeCycle is null - at those times it
|
|
677
|
-
* is only meaningful to look at ComponentLifeCycle alone.
|
|
678
|
-
*
|
|
679
|
-
* Top Row: ReactComponent.ComponentLifeCycle
|
|
680
|
-
* Low Row: ReactComponent.CompositeLifeCycle
|
|
681
|
-
*
|
|
682
|
-
* +-------+---------------------------------+--------+
|
|
683
|
-
* | UN | MOUNTED | UN |
|
|
684
|
-
* |MOUNTED| | MOUNTED|
|
|
685
|
-
* +-------+---------------------------------+--------+
|
|
686
|
-
* | ^--------+ +-------+ +--------^ |
|
|
687
|
-
* | | | | | | | |
|
|
688
|
-
* | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 |
|
|
689
|
-
* | | | |PROPS | |MOUNTING| |
|
|
690
|
-
* | | | | | | | |
|
|
691
|
-
* | | | | | | | |
|
|
692
|
-
* | +--------+ +-------+ +--------+ |
|
|
693
|
-
* | | | |
|
|
694
|
-
* +-------+---------------------------------+--------+
|
|
76
|
+
* @private
|
|
695
77
|
*/
|
|
696
|
-
var
|
|
697
|
-
/**
|
|
698
|
-
* Components in the process of being mounted respond to state changes
|
|
699
|
-
* differently.
|
|
700
|
-
*/
|
|
701
|
-
MOUNTING: null,
|
|
702
|
-
/**
|
|
703
|
-
* Components in the process of being unmounted are guarded against state
|
|
704
|
-
* changes.
|
|
705
|
-
*/
|
|
706
|
-
UNMOUNTING: null,
|
|
707
|
-
/**
|
|
708
|
-
* Components that are mounted and receiving new props respond to state
|
|
709
|
-
* changes differently.
|
|
710
|
-
*/
|
|
711
|
-
RECEIVING_PROPS: null
|
|
712
|
-
});
|
|
78
|
+
var nextMountID = 1;
|
|
713
79
|
|
|
714
80
|
/**
|
|
715
81
|
* @lends {ReactCompositeComponent.prototype}
|
|
@@ -724,29 +90,24 @@ var ReactCompositeComponentMixin = {
|
|
|
724
90
|
* @internal
|
|
725
91
|
*/
|
|
726
92
|
construct: function(element) {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
93
|
+
this._currentElement = element;
|
|
94
|
+
this._rootNodeID = null;
|
|
95
|
+
this._instance = null;
|
|
730
96
|
|
|
731
|
-
|
|
732
|
-
this.
|
|
97
|
+
// See ReactUpdateQueue
|
|
98
|
+
this._pendingElement = null;
|
|
99
|
+
this._pendingStateQueue = null;
|
|
100
|
+
this._pendingReplaceState = false;
|
|
101
|
+
this._pendingForceUpdate = false;
|
|
733
102
|
|
|
734
|
-
|
|
735
|
-
// context lives on the element.
|
|
736
|
-
this.context = null;
|
|
103
|
+
this._renderedComponent = null;
|
|
737
104
|
|
|
738
|
-
this.
|
|
739
|
-
|
|
105
|
+
this._context = null;
|
|
106
|
+
this._mountOrder = 0;
|
|
107
|
+
this._isTopLevel = false;
|
|
740
108
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
* @return {boolean} True if mounted, false otherwise.
|
|
744
|
-
* @protected
|
|
745
|
-
* @final
|
|
746
|
-
*/
|
|
747
|
-
isMounted: function() {
|
|
748
|
-
return ReactComponent.Mixin.isMounted.call(this) &&
|
|
749
|
-
this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
|
|
109
|
+
// See ReactUpdates and ReactUpdateQueue.
|
|
110
|
+
this._pendingCallbacks = null;
|
|
750
111
|
},
|
|
751
112
|
|
|
752
113
|
/**
|
|
@@ -754,68 +115,123 @@ var ReactCompositeComponentMixin = {
|
|
|
754
115
|
*
|
|
755
116
|
* @param {string} rootID DOM ID of the root node.
|
|
756
117
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
757
|
-
* @param {number} mountDepth number of components in the owner hierarchy
|
|
758
118
|
* @return {?string} Rendered markup to be inserted into the DOM.
|
|
759
119
|
* @final
|
|
760
120
|
* @internal
|
|
761
121
|
*/
|
|
762
|
-
mountComponent:
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
ReactComponent.Mixin.mountComponent.call(
|
|
767
|
-
this,
|
|
768
|
-
rootID,
|
|
769
|
-
transaction,
|
|
770
|
-
mountDepth
|
|
771
|
-
);
|
|
772
|
-
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
122
|
+
mountComponent: function(rootID, transaction, context) {
|
|
123
|
+
this._context = context;
|
|
124
|
+
this._mountOrder = nextMountID++;
|
|
125
|
+
this._rootNodeID = rootID;
|
|
773
126
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
127
|
+
var publicProps = this._processProps(this._currentElement.props);
|
|
128
|
+
var publicContext = this._processContext(this._currentElement._context);
|
|
777
129
|
|
|
778
|
-
|
|
779
|
-
this.
|
|
130
|
+
var Component = ReactNativeComponent.getComponentClassForElement(
|
|
131
|
+
this._currentElement
|
|
132
|
+
);
|
|
780
133
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
134
|
+
// Initialize the public class
|
|
135
|
+
var inst = new Component(publicProps, publicContext);
|
|
136
|
+
// These should be set up in the constructor, but as a convenience for
|
|
137
|
+
// simpler class abstractions, we set them up after the fact.
|
|
138
|
+
inst.props = publicProps;
|
|
139
|
+
inst.context = publicContext;
|
|
140
|
+
inst.refs = emptyObject;
|
|
787
141
|
|
|
788
|
-
|
|
789
|
-
|
|
142
|
+
this._instance = inst;
|
|
143
|
+
|
|
144
|
+
// Store a reference from the instance back to the internal representation
|
|
145
|
+
ReactInstanceMap.set(inst, this);
|
|
146
|
+
|
|
147
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
148
|
+
this._warnIfContextsDiffer(this._currentElement._context, context);
|
|
149
|
+
}
|
|
790
150
|
|
|
791
|
-
|
|
792
|
-
|
|
151
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
152
|
+
// Since plain JS classes are defined without any special initialization
|
|
153
|
+
// logic, we can not catch common errors early. Therefore, we have to
|
|
154
|
+
// catch them here, at initialization time, instead.
|
|
155
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
156
|
+
!inst.getInitialState ||
|
|
157
|
+
inst.getInitialState.isReactClassApproved,
|
|
158
|
+
'getInitialState was defined on %s, a plain JavaScript class. ' +
|
|
159
|
+
'This is only supported for classes created using React.createClass. ' +
|
|
160
|
+
'Did you mean to define a state property instead?',
|
|
161
|
+
this.getName() || 'a component'
|
|
162
|
+
) : null);
|
|
163
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
164
|
+
!inst.propTypes,
|
|
165
|
+
'propTypes was defined as an instance property on %s. Use a static ' +
|
|
166
|
+
'property to define propTypes instead.',
|
|
167
|
+
this.getName() || 'a component'
|
|
168
|
+
) : null);
|
|
169
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
170
|
+
!inst.contextTypes,
|
|
171
|
+
'contextTypes was defined as an instance property on %s. Use a ' +
|
|
172
|
+
'static property to define contextTypes instead.',
|
|
173
|
+
this.getName() || 'a component'
|
|
174
|
+
) : null);
|
|
175
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
176
|
+
typeof inst.componentShouldUpdate !== 'function',
|
|
177
|
+
'%s has a method called ' +
|
|
178
|
+
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
|
|
179
|
+
'The name is phrased as a question because the function is ' +
|
|
180
|
+
'expected to return a value.',
|
|
181
|
+
(this.getName() || 'A component')
|
|
182
|
+
) : null);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
var initialState = inst.state;
|
|
186
|
+
if (initialState === undefined) {
|
|
187
|
+
inst.state = initialState = null;
|
|
188
|
+
}
|
|
189
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
190
|
+
typeof initialState === 'object' && !Array.isArray(initialState),
|
|
191
|
+
'%s.state: must be set to an object or null',
|
|
192
|
+
this.getName() || 'ReactCompositeComponent'
|
|
193
|
+
) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
|
|
194
|
+
|
|
195
|
+
this._pendingStateQueue = null;
|
|
196
|
+
this._pendingReplaceState = false;
|
|
197
|
+
this._pendingForceUpdate = false;
|
|
198
|
+
|
|
199
|
+
var renderedElement;
|
|
200
|
+
|
|
201
|
+
var previouslyMounting = ReactLifeCycle.currentlyMountingInstance;
|
|
202
|
+
ReactLifeCycle.currentlyMountingInstance = this;
|
|
203
|
+
try {
|
|
204
|
+
if (inst.componentWillMount) {
|
|
205
|
+
inst.componentWillMount();
|
|
793
206
|
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
794
|
-
// `this.
|
|
795
|
-
if (this.
|
|
796
|
-
|
|
797
|
-
this._pendingState = null;
|
|
207
|
+
// `this._pendingStateQueue` without triggering a re-render.
|
|
208
|
+
if (this._pendingStateQueue) {
|
|
209
|
+
inst.state = this._processPendingState(inst.props, inst.context);
|
|
798
210
|
}
|
|
799
211
|
}
|
|
800
212
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
213
|
+
renderedElement = this._renderValidatedComponent();
|
|
214
|
+
} finally {
|
|
215
|
+
ReactLifeCycle.currentlyMountingInstance = previouslyMounting;
|
|
216
|
+
}
|
|
805
217
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
218
|
+
this._renderedComponent = this._instantiateReactComponent(
|
|
219
|
+
renderedElement,
|
|
220
|
+
this._currentElement.type // The wrapping type
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
var markup = ReactReconciler.mountComponent(
|
|
224
|
+
this._renderedComponent,
|
|
225
|
+
rootID,
|
|
226
|
+
transaction,
|
|
227
|
+
this._processChildContext(context)
|
|
228
|
+
);
|
|
229
|
+
if (inst.componentDidMount) {
|
|
230
|
+
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
|
|
817
231
|
}
|
|
818
|
-
|
|
232
|
+
|
|
233
|
+
return markup;
|
|
234
|
+
},
|
|
819
235
|
|
|
820
236
|
/**
|
|
821
237
|
* Releases any resources allocated by `mountComponent`.
|
|
@@ -824,83 +240,88 @@ var ReactCompositeComponentMixin = {
|
|
|
824
240
|
* @internal
|
|
825
241
|
*/
|
|
826
242
|
unmountComponent: function() {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
243
|
+
var inst = this._instance;
|
|
244
|
+
|
|
245
|
+
if (inst.componentWillUnmount) {
|
|
246
|
+
var previouslyUnmounting = ReactLifeCycle.currentlyUnmountingInstance;
|
|
247
|
+
ReactLifeCycle.currentlyUnmountingInstance = this;
|
|
248
|
+
try {
|
|
249
|
+
inst.componentWillUnmount();
|
|
250
|
+
} finally {
|
|
251
|
+
ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting;
|
|
252
|
+
}
|
|
830
253
|
}
|
|
831
|
-
this._compositeLifeCycleState = null;
|
|
832
254
|
|
|
833
|
-
this._renderedComponent
|
|
255
|
+
ReactReconciler.unmountComponent(this._renderedComponent);
|
|
834
256
|
this._renderedComponent = null;
|
|
835
257
|
|
|
836
|
-
|
|
258
|
+
// Reset pending fields
|
|
259
|
+
this._pendingStateQueue = null;
|
|
260
|
+
this._pendingReplaceState = false;
|
|
261
|
+
this._pendingForceUpdate = false;
|
|
262
|
+
this._pendingCallbacks = null;
|
|
263
|
+
this._pendingElement = null;
|
|
837
264
|
|
|
838
|
-
//
|
|
265
|
+
// These fields do not really need to be reset since this object is no
|
|
266
|
+
// longer accessible.
|
|
267
|
+
this._context = null;
|
|
268
|
+
this._rootNodeID = null;
|
|
269
|
+
|
|
270
|
+
// Delete the reference from the instance to this internal representation
|
|
271
|
+
// which allow the internals to be properly cleaned up even if the user
|
|
272
|
+
// leaks a reference to the public instance.
|
|
273
|
+
ReactInstanceMap.remove(inst);
|
|
274
|
+
|
|
275
|
+
// Some existing components rely on inst.props even after they've been
|
|
839
276
|
// destroyed (in event handlers).
|
|
840
|
-
// TODO:
|
|
841
|
-
// TODO:
|
|
277
|
+
// TODO: inst.props = null;
|
|
278
|
+
// TODO: inst.state = null;
|
|
279
|
+
// TODO: inst.context = null;
|
|
842
280
|
},
|
|
843
281
|
|
|
844
282
|
/**
|
|
845
|
-
*
|
|
846
|
-
* state. You should treat `this.state` as immutable.
|
|
847
|
-
*
|
|
848
|
-
* There is no guarantee that `this.state` will be immediately updated, so
|
|
849
|
-
* accessing `this.state` after calling this method may return the old value.
|
|
850
|
-
*
|
|
851
|
-
* There is no guarantee that calls to `setState` will run synchronously,
|
|
852
|
-
* as they may eventually be batched together. You can provide an optional
|
|
853
|
-
* callback that will be executed when the call to setState is actually
|
|
854
|
-
* completed.
|
|
283
|
+
* Schedule a partial update to the props. Only used for internal testing.
|
|
855
284
|
*
|
|
856
|
-
* @param {object}
|
|
857
|
-
* @param {?function} callback Called after
|
|
285
|
+
* @param {object} partialProps Subset of the next props.
|
|
286
|
+
* @param {?function} callback Called after props are updated.
|
|
858
287
|
* @final
|
|
859
|
-
* @
|
|
288
|
+
* @internal
|
|
860
289
|
*/
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
(
|
|
868
|
-
partialState != null,
|
|
869
|
-
'setState(...): You passed an undefined or null state object; ' +
|
|
870
|
-
'instead, use forceUpdate().'
|
|
871
|
-
) : null);
|
|
872
|
-
}
|
|
873
|
-
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
874
|
-
this.replaceState(
|
|
875
|
-
assign({}, this._pendingState || this.state, partialState),
|
|
876
|
-
callback
|
|
290
|
+
_setPropsInternal: function(partialProps, callback) {
|
|
291
|
+
// This is a deoptimized path. We optimize for always having an element.
|
|
292
|
+
// This creates an extra internal element.
|
|
293
|
+
var element = this._pendingElement || this._currentElement;
|
|
294
|
+
this._pendingElement = ReactElement.cloneAndReplaceProps(
|
|
295
|
+
element,
|
|
296
|
+
assign({}, element.props, partialProps)
|
|
877
297
|
);
|
|
298
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
878
299
|
},
|
|
879
300
|
|
|
880
301
|
/**
|
|
881
|
-
*
|
|
882
|
-
*
|
|
883
|
-
*
|
|
884
|
-
* There is no guarantee that `this.state` will be immediately updated, so
|
|
885
|
-
* accessing `this.state` after calling this method may return the old value.
|
|
302
|
+
* Filters the context object to only contain keys specified in
|
|
303
|
+
* `contextTypes`
|
|
886
304
|
*
|
|
887
|
-
* @param {object}
|
|
888
|
-
* @
|
|
889
|
-
* @
|
|
890
|
-
* @protected
|
|
305
|
+
* @param {object} context
|
|
306
|
+
* @return {?object}
|
|
307
|
+
* @private
|
|
891
308
|
*/
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
ReactUpdates.enqueueUpdate(this, callback);
|
|
309
|
+
_maskContext: function(context) {
|
|
310
|
+
var maskedContext = null;
|
|
311
|
+
// This really should be getting the component class for the element,
|
|
312
|
+
// but we know that we're not going to need it for built-ins.
|
|
313
|
+
if (typeof this._currentElement.type === 'string') {
|
|
314
|
+
return emptyObject;
|
|
315
|
+
}
|
|
316
|
+
var contextTypes = this._currentElement.type.contextTypes;
|
|
317
|
+
if (!contextTypes) {
|
|
318
|
+
return emptyObject;
|
|
903
319
|
}
|
|
320
|
+
maskedContext = {};
|
|
321
|
+
for (var contextName in contextTypes) {
|
|
322
|
+
maskedContext[contextName] = context[contextName];
|
|
323
|
+
}
|
|
324
|
+
return maskedContext;
|
|
904
325
|
},
|
|
905
326
|
|
|
906
327
|
/**
|
|
@@ -912,16 +333,14 @@ var ReactCompositeComponentMixin = {
|
|
|
912
333
|
* @private
|
|
913
334
|
*/
|
|
914
335
|
_processContext: function(context) {
|
|
915
|
-
var maskedContext =
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
336
|
+
var maskedContext = this._maskContext(context);
|
|
337
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
338
|
+
var Component = ReactNativeComponent.getComponentClassForElement(
|
|
339
|
+
this._currentElement
|
|
340
|
+
);
|
|
341
|
+
if (Component.contextTypes) {
|
|
923
342
|
this._checkPropTypes(
|
|
924
|
-
contextTypes,
|
|
343
|
+
Component.contextTypes,
|
|
925
344
|
maskedContext,
|
|
926
345
|
ReactPropTypeLocations.context
|
|
927
346
|
);
|
|
@@ -936,29 +355,29 @@ var ReactCompositeComponentMixin = {
|
|
|
936
355
|
* @private
|
|
937
356
|
*/
|
|
938
357
|
_processChildContext: function(currentContext) {
|
|
939
|
-
var
|
|
940
|
-
var
|
|
358
|
+
var inst = this._instance;
|
|
359
|
+
var childContext = inst.getChildContext && inst.getChildContext();
|
|
941
360
|
if (childContext) {
|
|
942
361
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
943
|
-
typeof
|
|
362
|
+
typeof inst.constructor.childContextTypes === 'object',
|
|
944
363
|
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
|
945
364
|
'use getChildContext().',
|
|
946
|
-
|
|
947
|
-
) : invariant(typeof
|
|
365
|
+
this.getName() || 'ReactCompositeComponent'
|
|
366
|
+
) : invariant(typeof inst.constructor.childContextTypes === 'object'));
|
|
948
367
|
if ("production" !== process.env.NODE_ENV) {
|
|
949
368
|
this._checkPropTypes(
|
|
950
|
-
|
|
369
|
+
inst.constructor.childContextTypes,
|
|
951
370
|
childContext,
|
|
952
371
|
ReactPropTypeLocations.childContext
|
|
953
372
|
);
|
|
954
373
|
}
|
|
955
374
|
for (var name in childContext) {
|
|
956
375
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
957
|
-
name in
|
|
376
|
+
name in inst.constructor.childContextTypes,
|
|
958
377
|
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
|
|
959
|
-
|
|
378
|
+
this.getName() || 'ReactCompositeComponent',
|
|
960
379
|
name
|
|
961
|
-
) : invariant(name in
|
|
380
|
+
) : invariant(name in inst.constructor.childContextTypes));
|
|
962
381
|
}
|
|
963
382
|
return assign({}, currentContext, childContext);
|
|
964
383
|
}
|
|
@@ -976,9 +395,15 @@ var ReactCompositeComponentMixin = {
|
|
|
976
395
|
*/
|
|
977
396
|
_processProps: function(newProps) {
|
|
978
397
|
if ("production" !== process.env.NODE_ENV) {
|
|
979
|
-
var
|
|
980
|
-
|
|
981
|
-
|
|
398
|
+
var Component = ReactNativeComponent.getComponentClassForElement(
|
|
399
|
+
this._currentElement
|
|
400
|
+
);
|
|
401
|
+
if (Component.propTypes) {
|
|
402
|
+
this._checkPropTypes(
|
|
403
|
+
Component.propTypes,
|
|
404
|
+
newProps,
|
|
405
|
+
ReactPropTypeLocations.prop
|
|
406
|
+
);
|
|
982
407
|
}
|
|
983
408
|
}
|
|
984
409
|
return newProps;
|
|
@@ -995,103 +420,236 @@ var ReactCompositeComponentMixin = {
|
|
|
995
420
|
_checkPropTypes: function(propTypes, props, location) {
|
|
996
421
|
// TODO: Stop validating prop types here and only use the element
|
|
997
422
|
// validation.
|
|
998
|
-
var componentName = this.
|
|
423
|
+
var componentName = this.getName();
|
|
999
424
|
for (var propName in propTypes) {
|
|
1000
425
|
if (propTypes.hasOwnProperty(propName)) {
|
|
1001
|
-
var error
|
|
1002
|
-
|
|
426
|
+
var error;
|
|
427
|
+
try {
|
|
428
|
+
// This is intentionally an invariant that gets caught. It's the same
|
|
429
|
+
// behavior as without this statement except with a better message.
|
|
430
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
431
|
+
typeof propTypes[propName] === 'function',
|
|
432
|
+
'%s: %s type `%s` is invalid; it must be a function, usually ' +
|
|
433
|
+
'from React.PropTypes.',
|
|
434
|
+
componentName || 'React class',
|
|
435
|
+
ReactPropTypeLocationNames[location],
|
|
436
|
+
propName
|
|
437
|
+
) : invariant(typeof propTypes[propName] === 'function'));
|
|
438
|
+
error = propTypes[propName](props, propName, componentName, location);
|
|
439
|
+
} catch (ex) {
|
|
440
|
+
error = ex;
|
|
441
|
+
}
|
|
1003
442
|
if (error instanceof Error) {
|
|
1004
443
|
// We may want to extend this logic for similar errors in
|
|
1005
|
-
//
|
|
444
|
+
// React.render calls, so I'm abstracting it away into
|
|
1006
445
|
// a function to minimize refactoring in the future
|
|
1007
446
|
var addendum = getDeclarationErrorAddendum(this);
|
|
1008
|
-
|
|
447
|
+
|
|
448
|
+
if (location === ReactPropTypeLocations.prop) {
|
|
449
|
+
// Preface gives us something to blacklist in warning module
|
|
450
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
451
|
+
false,
|
|
452
|
+
'Failed Composite propType: %s',
|
|
453
|
+
error.message + addendum
|
|
454
|
+
) : null);
|
|
455
|
+
} else {
|
|
456
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
457
|
+
false,
|
|
458
|
+
'Failed Context Types: %s',
|
|
459
|
+
error.message + addendum
|
|
460
|
+
) : null);
|
|
461
|
+
}
|
|
1009
462
|
}
|
|
1010
463
|
}
|
|
1011
464
|
}
|
|
1012
465
|
},
|
|
1013
466
|
|
|
467
|
+
receiveComponent: function(nextElement, transaction, nextContext) {
|
|
468
|
+
var prevElement = this._currentElement;
|
|
469
|
+
var prevContext = this._context;
|
|
470
|
+
|
|
471
|
+
this._pendingElement = null;
|
|
472
|
+
|
|
473
|
+
this.updateComponent(
|
|
474
|
+
transaction,
|
|
475
|
+
prevElement,
|
|
476
|
+
nextElement,
|
|
477
|
+
prevContext,
|
|
478
|
+
nextContext
|
|
479
|
+
);
|
|
480
|
+
},
|
|
481
|
+
|
|
1014
482
|
/**
|
|
1015
|
-
* If any of `_pendingElement`, `
|
|
483
|
+
* If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
|
|
1016
484
|
* is set, update the component.
|
|
1017
485
|
*
|
|
1018
486
|
* @param {ReactReconcileTransaction} transaction
|
|
1019
487
|
* @internal
|
|
1020
488
|
*/
|
|
1021
489
|
performUpdateIfNecessary: function(transaction) {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
490
|
+
if (this._pendingElement != null) {
|
|
491
|
+
ReactReconciler.receiveComponent(
|
|
492
|
+
this,
|
|
493
|
+
this._pendingElement || this._currentElement,
|
|
494
|
+
transaction,
|
|
495
|
+
this._context
|
|
496
|
+
);
|
|
1028
497
|
}
|
|
1029
498
|
|
|
1030
|
-
if (this.
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
499
|
+
if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
|
|
500
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
501
|
+
ReactElementValidator.checkAndWarnForMutatedProps(
|
|
502
|
+
this._currentElement
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
this.updateComponent(
|
|
507
|
+
transaction,
|
|
508
|
+
this._currentElement,
|
|
509
|
+
this._currentElement,
|
|
510
|
+
this._context,
|
|
511
|
+
this._context
|
|
512
|
+
);
|
|
1034
513
|
}
|
|
514
|
+
},
|
|
1035
515
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
516
|
+
/**
|
|
517
|
+
* Compare two contexts, warning if they are different
|
|
518
|
+
* TODO: Remove this check when owner-context is removed
|
|
519
|
+
*/
|
|
520
|
+
_warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
|
|
521
|
+
ownerBasedContext = this._maskContext(ownerBasedContext);
|
|
522
|
+
parentBasedContext = this._maskContext(parentBasedContext);
|
|
523
|
+
var parentKeys = Object.keys(parentBasedContext).sort();
|
|
524
|
+
var displayName = this.getName() || 'ReactCompositeComponent';
|
|
525
|
+
for (var i = 0; i < parentKeys.length; i++) {
|
|
526
|
+
var key = parentKeys[i];
|
|
527
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
528
|
+
ownerBasedContext[key] === parentBasedContext[key],
|
|
529
|
+
'owner-based and parent-based contexts differ ' +
|
|
530
|
+
'(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
|
|
531
|
+
'(see: http://fb.me/react-context-by-parent)',
|
|
532
|
+
ownerBasedContext[key],
|
|
533
|
+
parentBasedContext[key],
|
|
534
|
+
key,
|
|
535
|
+
displayName
|
|
536
|
+
) : null);
|
|
1049
537
|
}
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Perform an update to a mounted component. The componentWillReceiveProps and
|
|
542
|
+
* shouldComponentUpdate methods are called, then (assuming the update isn't
|
|
543
|
+
* skipped) the remaining update lifecycle methods are called and the DOM
|
|
544
|
+
* representation is updated.
|
|
545
|
+
*
|
|
546
|
+
* By default, this implements React's rendering and reconciliation algorithm.
|
|
547
|
+
* Sophisticated clients may wish to override this.
|
|
548
|
+
*
|
|
549
|
+
* @param {ReactReconcileTransaction} transaction
|
|
550
|
+
* @param {ReactElement} prevParentElement
|
|
551
|
+
* @param {ReactElement} nextParentElement
|
|
552
|
+
* @internal
|
|
553
|
+
* @overridable
|
|
554
|
+
*/
|
|
555
|
+
updateComponent: function(
|
|
556
|
+
transaction,
|
|
557
|
+
prevParentElement,
|
|
558
|
+
nextParentElement,
|
|
559
|
+
prevUnmaskedContext,
|
|
560
|
+
nextUnmaskedContext
|
|
561
|
+
) {
|
|
562
|
+
var inst = this._instance;
|
|
563
|
+
|
|
564
|
+
var nextContext = inst.context;
|
|
565
|
+
var nextProps = inst.props;
|
|
1050
566
|
|
|
1051
|
-
|
|
567
|
+
// Distinguish between a props update versus a simple state update
|
|
568
|
+
if (prevParentElement !== nextParentElement) {
|
|
569
|
+
nextContext = this._processContext(nextParentElement._context);
|
|
570
|
+
nextProps = this._processProps(nextParentElement.props);
|
|
1052
571
|
|
|
1053
|
-
|
|
1054
|
-
|
|
572
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
573
|
+
if (nextUnmaskedContext != null) {
|
|
574
|
+
this._warnIfContextsDiffer(
|
|
575
|
+
nextParentElement._context,
|
|
576
|
+
nextUnmaskedContext
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// An update here will schedule an update but immediately set
|
|
582
|
+
// _pendingStateQueue which will ensure that any state updates gets
|
|
583
|
+
// immediately reconciled instead of waiting for the next batch.
|
|
584
|
+
|
|
585
|
+
if (inst.componentWillReceiveProps) {
|
|
586
|
+
inst.componentWillReceiveProps(nextProps, nextContext);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
var nextState = this._processPendingState(nextProps, nextContext);
|
|
1055
591
|
|
|
1056
592
|
var shouldUpdate =
|
|
1057
593
|
this._pendingForceUpdate ||
|
|
1058
|
-
!
|
|
1059
|
-
|
|
594
|
+
!inst.shouldComponentUpdate ||
|
|
595
|
+
inst.shouldComponentUpdate(nextProps, nextState, nextContext);
|
|
1060
596
|
|
|
1061
597
|
if ("production" !== process.env.NODE_ENV) {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
}
|
|
598
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
599
|
+
typeof shouldUpdate !== 'undefined',
|
|
600
|
+
'%s.shouldComponentUpdate(): Returned undefined instead of a ' +
|
|
601
|
+
'boolean value. Make sure to return true or false.',
|
|
602
|
+
this.getName() || 'ReactCompositeComponent'
|
|
603
|
+
) : null);
|
|
1069
604
|
}
|
|
1070
605
|
|
|
1071
606
|
if (shouldUpdate) {
|
|
1072
607
|
this._pendingForceUpdate = false;
|
|
1073
608
|
// Will set `this.props`, `this.state` and `this.context`.
|
|
1074
609
|
this._performComponentUpdate(
|
|
1075
|
-
|
|
610
|
+
nextParentElement,
|
|
1076
611
|
nextProps,
|
|
1077
612
|
nextState,
|
|
1078
613
|
nextContext,
|
|
1079
|
-
transaction
|
|
614
|
+
transaction,
|
|
615
|
+
nextUnmaskedContext
|
|
1080
616
|
);
|
|
1081
617
|
} else {
|
|
1082
618
|
// 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
|
-
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
|
1090
|
-
// it. TODO: Remove this._owner completely.
|
|
1091
|
-
this._owner = nextElement._owner;
|
|
619
|
+
// to set props and state but we shortcut the rest of the update.
|
|
620
|
+
this._currentElement = nextParentElement;
|
|
621
|
+
this._context = nextUnmaskedContext;
|
|
622
|
+
inst.props = nextProps;
|
|
623
|
+
inst.state = nextState;
|
|
624
|
+
inst.context = nextContext;
|
|
1092
625
|
}
|
|
1093
626
|
},
|
|
1094
627
|
|
|
628
|
+
_processPendingState: function(props, context) {
|
|
629
|
+
var inst = this._instance;
|
|
630
|
+
var queue = this._pendingStateQueue;
|
|
631
|
+
var replace = this._pendingReplaceState;
|
|
632
|
+
this._pendingReplaceState = false;
|
|
633
|
+
this._pendingStateQueue = null;
|
|
634
|
+
|
|
635
|
+
if (!queue) {
|
|
636
|
+
return inst.state;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
var nextState = assign({}, replace ? queue[0] : inst.state);
|
|
640
|
+
for (var i = replace ? 1 : 0; i < queue.length; i++) {
|
|
641
|
+
var partial = queue[i];
|
|
642
|
+
assign(
|
|
643
|
+
nextState,
|
|
644
|
+
typeof partial === 'function' ?
|
|
645
|
+
partial.call(inst, nextState, props, context) :
|
|
646
|
+
partial
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return nextState;
|
|
651
|
+
},
|
|
652
|
+
|
|
1095
653
|
/**
|
|
1096
654
|
* Merges new props and state, notifies delegate methods of update and
|
|
1097
655
|
* performs update.
|
|
@@ -1101,6 +659,7 @@ var ReactCompositeComponentMixin = {
|
|
|
1101
659
|
* @param {?object} nextState Next object to set as state.
|
|
1102
660
|
* @param {?object} nextContext Next public object to set as context.
|
|
1103
661
|
* @param {ReactReconcileTransaction} transaction
|
|
662
|
+
* @param {?object} unmaskedContext
|
|
1104
663
|
* @private
|
|
1105
664
|
*/
|
|
1106
665
|
_performComponentUpdate: function(
|
|
@@ -1108,329 +667,204 @@ var ReactCompositeComponentMixin = {
|
|
|
1108
667
|
nextProps,
|
|
1109
668
|
nextState,
|
|
1110
669
|
nextContext,
|
|
1111
|
-
transaction
|
|
670
|
+
transaction,
|
|
671
|
+
unmaskedContext
|
|
1112
672
|
) {
|
|
1113
|
-
var
|
|
1114
|
-
var prevProps = this.props;
|
|
1115
|
-
var prevState = this.state;
|
|
1116
|
-
var prevContext = this.context;
|
|
673
|
+
var inst = this._instance;
|
|
1117
674
|
|
|
1118
|
-
|
|
1119
|
-
|
|
675
|
+
var prevProps = inst.props;
|
|
676
|
+
var prevState = inst.state;
|
|
677
|
+
var prevContext = inst.context;
|
|
678
|
+
|
|
679
|
+
if (inst.componentWillUpdate) {
|
|
680
|
+
inst.componentWillUpdate(nextProps, nextState, nextContext);
|
|
1120
681
|
}
|
|
1121
682
|
|
|
1122
683
|
this._currentElement = nextElement;
|
|
1123
|
-
this.
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
|
1128
|
-
// it. TODO: Remove this._owner completely.
|
|
1129
|
-
this._owner = nextElement._owner;
|
|
684
|
+
this._context = unmaskedContext;
|
|
685
|
+
inst.props = nextProps;
|
|
686
|
+
inst.state = nextState;
|
|
687
|
+
inst.context = nextContext;
|
|
1130
688
|
|
|
1131
|
-
this.
|
|
1132
|
-
transaction,
|
|
1133
|
-
prevElement
|
|
1134
|
-
);
|
|
689
|
+
this._updateRenderedComponent(transaction, unmaskedContext);
|
|
1135
690
|
|
|
1136
|
-
if (
|
|
691
|
+
if (inst.componentDidUpdate) {
|
|
1137
692
|
transaction.getReactMountReady().enqueue(
|
|
1138
|
-
|
|
1139
|
-
|
|
693
|
+
inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext),
|
|
694
|
+
inst
|
|
1140
695
|
);
|
|
1141
696
|
}
|
|
1142
697
|
},
|
|
1143
698
|
|
|
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
699
|
/**
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
* By default, this implements React's rendering and reconciliation algorithm.
|
|
1168
|
-
* Sophisticated clients may wish to override this.
|
|
700
|
+
* Call the component's `render` method and update the DOM accordingly.
|
|
1169
701
|
*
|
|
1170
702
|
* @param {ReactReconcileTransaction} transaction
|
|
1171
|
-
* @param {ReactElement} prevElement
|
|
1172
703
|
* @internal
|
|
1173
|
-
* @overridable
|
|
1174
704
|
*/
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
705
|
+
_updateRenderedComponent: function(transaction, context) {
|
|
706
|
+
var prevComponentInstance = this._renderedComponent;
|
|
707
|
+
var prevRenderedElement = prevComponentInstance._currentElement;
|
|
708
|
+
var nextRenderedElement = this._renderValidatedComponent();
|
|
709
|
+
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
|
|
710
|
+
ReactReconciler.receiveComponent(
|
|
711
|
+
prevComponentInstance,
|
|
712
|
+
nextRenderedElement,
|
|
1181
713
|
transaction,
|
|
1182
|
-
|
|
714
|
+
this._processChildContext(context)
|
|
1183
715
|
);
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
var
|
|
1187
|
-
var
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
this._renderedComponent
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
transaction,
|
|
1202
|
-
this._mountDepth + 1
|
|
1203
|
-
);
|
|
1204
|
-
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
|
|
1205
|
-
prevComponentID,
|
|
1206
|
-
nextMarkup
|
|
1207
|
-
);
|
|
1208
|
-
}
|
|
716
|
+
} else {
|
|
717
|
+
// These two IDs are actually the same! But nothing should rely on that.
|
|
718
|
+
var thisID = this._rootNodeID;
|
|
719
|
+
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
720
|
+
ReactReconciler.unmountComponent(prevComponentInstance);
|
|
721
|
+
|
|
722
|
+
this._renderedComponent = this._instantiateReactComponent(
|
|
723
|
+
nextRenderedElement,
|
|
724
|
+
this._currentElement.type
|
|
725
|
+
);
|
|
726
|
+
var nextMarkup = ReactReconciler.mountComponent(
|
|
727
|
+
this._renderedComponent,
|
|
728
|
+
thisID,
|
|
729
|
+
transaction,
|
|
730
|
+
context
|
|
731
|
+
);
|
|
732
|
+
this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
|
|
1209
733
|
}
|
|
1210
|
-
|
|
734
|
+
},
|
|
1211
735
|
|
|
1212
736
|
/**
|
|
1213
|
-
* Forces an update. This should only be invoked when it is known with
|
|
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
737
|
* @protected
|
|
1225
738
|
*/
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
'forceUpdate(...): Can only force an update on mounted or mounting ' +
|
|
1232
|
-
'components.'
|
|
1233
|
-
) : invariant(this.isMounted() ||
|
|
1234
|
-
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
|
|
1235
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
1236
|
-
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
|
|
1237
|
-
ReactCurrentOwner.current == null,
|
|
1238
|
-
'forceUpdate(...): Cannot force an update while unmounting component ' +
|
|
1239
|
-
'or within a `render` function.'
|
|
1240
|
-
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
|
|
1241
|
-
ReactCurrentOwner.current == null));
|
|
1242
|
-
this._pendingForceUpdate = true;
|
|
1243
|
-
ReactUpdates.enqueueUpdate(this, callback);
|
|
739
|
+
_replaceNodeWithMarkupByID: function(prevComponentID, nextMarkup) {
|
|
740
|
+
ReactComponentEnvironment.replaceNodeWithMarkupByID(
|
|
741
|
+
prevComponentID,
|
|
742
|
+
nextMarkup
|
|
743
|
+
);
|
|
1244
744
|
},
|
|
1245
745
|
|
|
1246
746
|
/**
|
|
1247
|
-
* @
|
|
747
|
+
* @protected
|
|
1248
748
|
*/
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
try {
|
|
1260
|
-
renderedComponent = this.render();
|
|
1261
|
-
if (renderedComponent === null || renderedComponent === false) {
|
|
1262
|
-
renderedComponent = ReactEmptyComponent.getEmptyComponent();
|
|
1263
|
-
ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
|
|
1264
|
-
} else {
|
|
1265
|
-
ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
|
|
1266
|
-
}
|
|
1267
|
-
} finally {
|
|
1268
|
-
ReactContext.current = previousContext;
|
|
1269
|
-
ReactCurrentOwner.current = null;
|
|
749
|
+
_renderValidatedComponentWithoutOwnerOrContext: function() {
|
|
750
|
+
var inst = this._instance;
|
|
751
|
+
var renderedComponent = inst.render();
|
|
752
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
753
|
+
// We allow auto-mocks to proceed as if they're returning null.
|
|
754
|
+
if (typeof renderedComponent === 'undefined' &&
|
|
755
|
+
inst.render._isMockFunction) {
|
|
756
|
+
// This is probably bad practice. Consider warning here and
|
|
757
|
+
// deprecating this convenience.
|
|
758
|
+
renderedComponent = null;
|
|
1270
759
|
}
|
|
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;
|
|
1278
760
|
}
|
|
1279
|
-
|
|
761
|
+
|
|
762
|
+
return renderedComponent;
|
|
763
|
+
},
|
|
1280
764
|
|
|
1281
765
|
/**
|
|
1282
766
|
* @private
|
|
1283
767
|
*/
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
768
|
+
_renderValidatedComponent: function() {
|
|
769
|
+
var renderedComponent;
|
|
770
|
+
var previousContext = ReactContext.current;
|
|
771
|
+
ReactContext.current = this._processChildContext(
|
|
772
|
+
this._currentElement._context
|
|
773
|
+
);
|
|
774
|
+
ReactCurrentOwner.current = this;
|
|
775
|
+
try {
|
|
776
|
+
renderedComponent =
|
|
777
|
+
this._renderValidatedComponentWithoutOwnerOrContext();
|
|
778
|
+
} finally {
|
|
779
|
+
ReactContext.current = previousContext;
|
|
780
|
+
ReactCurrentOwner.current = null;
|
|
1294
781
|
}
|
|
782
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
783
|
+
// TODO: An `isValidNode` function would probably be more appropriate
|
|
784
|
+
renderedComponent === null || renderedComponent === false ||
|
|
785
|
+
ReactElement.isValidElement(renderedComponent),
|
|
786
|
+
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
787
|
+
'returned undefined, an array or some other invalid object.',
|
|
788
|
+
this.getName() || 'ReactCompositeComponent'
|
|
789
|
+
) : invariant(// TODO: An `isValidNode` function would probably be more appropriate
|
|
790
|
+
renderedComponent === null || renderedComponent === false ||
|
|
791
|
+
ReactElement.isValidElement(renderedComponent)));
|
|
792
|
+
return renderedComponent;
|
|
1295
793
|
},
|
|
1296
794
|
|
|
1297
795
|
/**
|
|
1298
|
-
*
|
|
796
|
+
* Lazily allocates the refs object and stores `component` as `ref`.
|
|
1299
797
|
*
|
|
1300
|
-
* @param {
|
|
798
|
+
* @param {string} ref Reference name.
|
|
799
|
+
* @param {component} component Component to store as `ref`.
|
|
800
|
+
* @final
|
|
1301
801
|
* @private
|
|
1302
802
|
*/
|
|
1303
|
-
|
|
1304
|
-
var
|
|
1305
|
-
var
|
|
1306
|
-
|
|
1307
|
-
|
|
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
|
-
};
|
|
1341
|
-
|
|
1342
|
-
var ReactCompositeComponentBase = function() {};
|
|
1343
|
-
assign(
|
|
1344
|
-
ReactCompositeComponentBase.prototype,
|
|
1345
|
-
ReactComponent.Mixin,
|
|
1346
|
-
ReactOwner.Mixin,
|
|
1347
|
-
ReactPropTransferer.Mixin,
|
|
1348
|
-
ReactCompositeComponentMixin
|
|
1349
|
-
);
|
|
1350
|
-
|
|
1351
|
-
/**
|
|
1352
|
-
* Module for creating composite components.
|
|
1353
|
-
*
|
|
1354
|
-
* @class ReactCompositeComponent
|
|
1355
|
-
* @extends ReactComponent
|
|
1356
|
-
* @extends ReactOwner
|
|
1357
|
-
* @extends ReactPropTransferer
|
|
1358
|
-
*/
|
|
1359
|
-
var ReactCompositeComponent = {
|
|
1360
|
-
|
|
1361
|
-
LifeCycle: CompositeLifeCycle,
|
|
1362
|
-
|
|
1363
|
-
Base: ReactCompositeComponentBase,
|
|
803
|
+
attachRef: function(ref, component) {
|
|
804
|
+
var inst = this.getPublicInstance();
|
|
805
|
+
var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
|
|
806
|
+
refs[ref] = component.getPublicInstance();
|
|
807
|
+
},
|
|
1364
808
|
|
|
1365
809
|
/**
|
|
1366
|
-
*
|
|
810
|
+
* Detaches a reference name.
|
|
1367
811
|
*
|
|
1368
|
-
* @param {
|
|
1369
|
-
* @
|
|
1370
|
-
* @
|
|
812
|
+
* @param {string} ref Name to dereference.
|
|
813
|
+
* @final
|
|
814
|
+
* @private
|
|
1371
815
|
*/
|
|
1372
|
-
|
|
1373
|
-
var
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
816
|
+
detachRef: function(ref) {
|
|
817
|
+
var refs = this.getPublicInstance().refs;
|
|
818
|
+
delete refs[ref];
|
|
819
|
+
},
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Get a text description of the component that can be used to identify it
|
|
823
|
+
* in error messages.
|
|
824
|
+
* @return {string} The name or null.
|
|
825
|
+
* @internal
|
|
826
|
+
*/
|
|
827
|
+
getName: function() {
|
|
828
|
+
var type = this._currentElement.type;
|
|
829
|
+
var constructor = this._instance && this._instance.constructor;
|
|
830
|
+
return (
|
|
831
|
+
type.displayName || (constructor && constructor.displayName) ||
|
|
832
|
+
type.name || (constructor && constructor.name) ||
|
|
833
|
+
null
|
|
1383
834
|
);
|
|
835
|
+
},
|
|
1384
836
|
|
|
1385
|
-
|
|
837
|
+
/**
|
|
838
|
+
* Get the publicly accessible representation of this component - i.e. what
|
|
839
|
+
* is exposed by refs and returned by React.render. Can be null for stateless
|
|
840
|
+
* components.
|
|
841
|
+
*
|
|
842
|
+
* @return {ReactComponent} the public component instance.
|
|
843
|
+
* @internal
|
|
844
|
+
*/
|
|
845
|
+
getPublicInstance: function() {
|
|
846
|
+
return this._instance;
|
|
847
|
+
},
|
|
1386
848
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
Constructor.defaultProps = Constructor.getDefaultProps();
|
|
1390
|
-
}
|
|
849
|
+
// Stub
|
|
850
|
+
_instantiateReactComponent: null
|
|
1391
851
|
|
|
1392
|
-
|
|
1393
|
-
Constructor.prototype.render,
|
|
1394
|
-
'createClass(...): Class specification must implement a `render` method.'
|
|
1395
|
-
) : invariant(Constructor.prototype.render));
|
|
852
|
+
};
|
|
1396
853
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
'The name is phrased as a question because the function is ' +
|
|
1407
|
-
'expected to return a value.'
|
|
1408
|
-
);
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
854
|
+
ReactPerf.measureMethods(
|
|
855
|
+
ReactCompositeComponentMixin,
|
|
856
|
+
'ReactCompositeComponent',
|
|
857
|
+
{
|
|
858
|
+
mountComponent: 'mountComponent',
|
|
859
|
+
updateComponent: 'updateComponent',
|
|
860
|
+
_renderValidatedComponent: '_renderValidatedComponent'
|
|
861
|
+
}
|
|
862
|
+
);
|
|
1411
863
|
|
|
1412
|
-
|
|
1413
|
-
for (var methodName in ReactCompositeComponentInterface) {
|
|
1414
|
-
if (!Constructor.prototype[methodName]) {
|
|
1415
|
-
Constructor.prototype[methodName] = null;
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
864
|
+
var ReactCompositeComponent = {
|
|
1418
865
|
|
|
1419
|
-
|
|
1420
|
-
return ReactLegacyElement.wrapFactory(
|
|
1421
|
-
ReactElementValidator.createFactory(Constructor)
|
|
1422
|
-
);
|
|
1423
|
-
}
|
|
1424
|
-
return ReactLegacyElement.wrapFactory(
|
|
1425
|
-
ReactElement.createFactory(Constructor)
|
|
1426
|
-
);
|
|
1427
|
-
},
|
|
866
|
+
Mixin: ReactCompositeComponentMixin
|
|
1428
867
|
|
|
1429
|
-
injection: {
|
|
1430
|
-
injectMixin: function(mixin) {
|
|
1431
|
-
injectedMixins.push(mixin);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
868
|
};
|
|
1435
869
|
|
|
1436
870
|
module.exports = ReactCompositeComponent;
|