UNPKG

6.09 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var ReactRef = require('./ReactRef');
12var ReactInstrumentation = require('./ReactInstrumentation');
13
14var warning = require('fbjs/lib/warning');
15
16/**
17 * Helper to call ReactRef.attachRefs with this composite component, split out
18 * to avoid allocations in the transaction mount-ready queue.
19 */
20function attachRefs() {
21 ReactRef.attachRefs(this, this._currentElement);
22}
23
24var ReactReconciler = {
25 /**
26 * Initializes the component, renders markup, and registers event listeners.
27 *
28 * @param {ReactComponent} internalInstance
29 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
30 * @param {?object} the containing host component instance
31 * @param {?object} info about the host container
32 * @return {?string} Rendered markup to be inserted into the DOM.
33 * @final
34 * @internal
35 */
36 mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context, parentDebugID) // 0 in production and for roots
37 {
38 if (process.env.NODE_ENV !== 'production') {
39 if (internalInstance._debugID !== 0) {
40 ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement, parentDebugID);
41 }
42 }
43 var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context, parentDebugID);
44 if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {
45 transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
46 }
47 if (process.env.NODE_ENV !== 'production') {
48 if (internalInstance._debugID !== 0) {
49 ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);
50 }
51 }
52 return markup;
53 },
54
55 /**
56 * Returns a value that can be passed to
57 * ReactComponentEnvironment.replaceNodeWithMarkup.
58 */
59 getHostNode: function (internalInstance) {
60 return internalInstance.getHostNode();
61 },
62
63 /**
64 * Releases any resources allocated by `mountComponent`.
65 *
66 * @final
67 * @internal
68 */
69 unmountComponent: function (internalInstance, safely) {
70 if (process.env.NODE_ENV !== 'production') {
71 if (internalInstance._debugID !== 0) {
72 ReactInstrumentation.debugTool.onBeforeUnmountComponent(internalInstance._debugID);
73 }
74 }
75 ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
76 internalInstance.unmountComponent(safely);
77 if (process.env.NODE_ENV !== 'production') {
78 if (internalInstance._debugID !== 0) {
79 ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);
80 }
81 }
82 },
83
84 /**
85 * Update a component using a new element.
86 *
87 * @param {ReactComponent} internalInstance
88 * @param {ReactElement} nextElement
89 * @param {ReactReconcileTransaction} transaction
90 * @param {object} context
91 * @internal
92 */
93 receiveComponent: function (internalInstance, nextElement, transaction, context) {
94 var prevElement = internalInstance._currentElement;
95
96 if (nextElement === prevElement && context === internalInstance._context) {
97 // Since elements are immutable after the owner is rendered,
98 // we can do a cheap identity compare here to determine if this is a
99 // superfluous reconcile. It's possible for state to be mutable but such
100 // change should trigger an update of the owner which would recreate
101 // the element. We explicitly check for the existence of an owner since
102 // it's possible for an element created outside a composite to be
103 // deeply mutated and reused.
104
105 // TODO: Bailing out early is just a perf optimization right?
106 // TODO: Removing the return statement should affect correctness?
107 return;
108 }
109
110 if (process.env.NODE_ENV !== 'production') {
111 if (internalInstance._debugID !== 0) {
112 ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);
113 }
114 }
115
116 var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);
117
118 if (refsChanged) {
119 ReactRef.detachRefs(internalInstance, prevElement);
120 }
121
122 internalInstance.receiveComponent(nextElement, transaction, context);
123
124 if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {
125 transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
126 }
127
128 if (process.env.NODE_ENV !== 'production') {
129 if (internalInstance._debugID !== 0) {
130 ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
131 }
132 }
133 },
134
135 /**
136 * Flush any dirty changes in a component.
137 *
138 * @param {ReactComponent} internalInstance
139 * @param {ReactReconcileTransaction} transaction
140 * @internal
141 */
142 performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {
143 if (internalInstance._updateBatchNumber !== updateBatchNumber) {
144 // The component's enqueued batch number should always be the current
145 // batch or the following one.
146 process.env.NODE_ENV !== 'production' ? warning(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1, 'performUpdateIfNecessary: Unexpected batch number (current %s, ' + 'pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;
147 return;
148 }
149 if (process.env.NODE_ENV !== 'production') {
150 if (internalInstance._debugID !== 0) {
151 ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);
152 }
153 }
154 internalInstance.performUpdateIfNecessary(transaction);
155 if (process.env.NODE_ENV !== 'production') {
156 if (internalInstance._debugID !== 0) {
157 ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
158 }
159 }
160 }
161};
162
163module.exports = ReactReconciler;
\No newline at end of file