UNPKG

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