forked from facebook/react
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReactComponentBrowserEnvironment.js
137 lines (122 loc) · 4.32 KB
/
ReactComponentBrowserEnvironment.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule ReactComponentBrowserEnvironment
*/
/*jslint evil: true */
"use strict";
var ReactDOMIDOperations = require('ReactDOMIDOperations');
var ReactMarkupChecksum = require('ReactMarkupChecksum');
var ReactMount = require('ReactMount');
var ReactReconcileTransaction = require('ReactReconcileTransaction');
var getReactRootElementInContainer = require('getReactRootElementInContainer');
var invariant = require('invariant');
var mutateHTMLNodeWithMarkup = require('mutateHTMLNodeWithMarkup');
var ELEMENT_NODE_TYPE = 1;
var DOC_NODE_TYPE = 9;
/**
* Abstracts away all functionality of `ReactComponent` requires knowledge of
* the browser context.
*/
var ReactComponentBrowserEnvironment = {
/**
* Mixed into every component instance.
*/
Mixin: {
/**
* Returns the DOM node rendered by this component.
*
* @return {DOMElement} The root node of this component.
* @final
* @protected
*/
getDOMNode: function() {
invariant(
this.isMounted(),
'getDOMNode(): A component must be mounted to have a DOM node.'
);
return ReactMount.getNode(this._rootNodeID);
}
},
ReactReconcileTransaction: ReactReconcileTransaction,
DOMIDOperations: ReactDOMIDOperations,
/**
* If a particular environment requires that some resources be cleaned up,
* specify this in the injected Mixin. In the DOM, we would likely want to
* purge any cached node ID lookups.
*
* @private
*/
unmountIDFromEnvironment: function(rootNodeID) {
ReactMount.purgeID(rootNodeID);
},
/**
* @param {string} markup Markup string to place into the DOM Element.
* @param {DOMElement} container DOM Element to insert markup into.
* @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
* container if possible.
*/
mountImageIntoNode: function(markup, container, shouldReuseMarkup) {
invariant(
container && (
container.nodeType === ELEMENT_NODE_TYPE ||
container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender
),
'mountComponentIntoNode(...): Target container is not valid.'
);
if (shouldReuseMarkup) {
if (ReactMarkupChecksum.canReuseMarkup(
markup,
getReactRootElementInContainer(container))) {
return;
} else {
if (__DEV__) {
console.warn(
'React attempted to use reuse markup in a container but the ' +
'checksum was invalid. This generally means that you are using ' +
'server rendering and the markup generated on the server was ' +
'not what the client was expecting. React injected new markup ' +
'to compensate which works but you have lost many of the ' +
'benefits of server rendering. Instead, figure out why the ' +
'markup being generated is different on the client or server.'
);
}
}
}
// You can't naively set the innerHTML of the entire document. You need
// to mutate documentElement which requires doing some crazy tricks. See
// mutateHTMLNodeWithMarkup()
if (container.nodeType === DOC_NODE_TYPE) {
mutateHTMLNodeWithMarkup(container.documentElement, markup);
return;
}
// Asynchronously inject markup by ensuring that the container is not in
// the document when settings its `innerHTML`.
var parent = container.parentNode;
if (parent) {
var next = container.nextSibling;
parent.removeChild(container);
container.innerHTML = markup;
if (next) {
parent.insertBefore(container, next);
} else {
parent.appendChild(container);
}
} else {
container.innerHTML = markup;
}
}
};
module.exports = ReactComponentBrowserEnvironment;