ReactMount now never expects invalid nodes in its cache
It never really made sense for us to have "invalid" nodes in the cache -- when we unmount things, we should always remove them from the cache properly. Now that swapping composite types doesn't repopulate the cache, we should be okay to now assume that everything in the cache is good.
Ben Alpert committed
Sep 26, 2015 at 15:11 UTC
8ce7b7120cff9f46237fef73120c9ddca25e30fc
1 file changed
+34
-24
src/renderers/dom/client/ReactMount.js
+34
-24
@@ -100,7 +100,7 @@ function getReactRootElementInContainer(container) {
100
*/
101
function getReactRootID(container) {
102
var rootElement = getReactRootElementInContainer(container);
103
- return rootElement && ReactMount.getID(rootElement);
103
+ return rootElement && internalGetID(rootElement);
104
}
105
106
/**
@@ -116,20 +116,12 @@ function getReactRootID(container) {
116
function getID(node) {
117
var id = internalGetID(node);
118
if (id) {
119
- if (nodeCache.hasOwnProperty(id)) {
120
- var cached = nodeCache[id];
121
- if (cached !== node) {
122
- invariant(
123
- !isValid(cached, id),
124
- 'ReactMount: Two valid but unequal nodes with the same `%s`: %s',
125
- ATTR_NAME, id
126
- );
127
-
128
- nodeCache[id] = node;
129
- }
130
- } else {
131
- nodeCache[id] = node;
132
- }
119
+ invariant(
120
+ !nodeCache.hasOwnProperty(id) || nodeCache[id] === node,
121
+ 'ReactMount: Two unequal nodes with the same `%s`: %s',
122
+ ATTR_NAME, id
123
+ );
124
+ nodeCache[id] = node;
125
}
126
127
return id;
@@ -157,6 +149,25 @@ function setID(node, id) {
149
nodeCache[id] = node;
150
}
151
152
+/**
153
+ * Finds the node with the supplied ID if present in the cache.
154
+ */
155
+function getNodeIfCached(id) {
156
+ var node = nodeCache[id];
157
+ // TODO: Since this "isValid" business is now just a sanity check, we can
158
+ // probably drop it with no consequences.
159
+ invariant(
160
+ !node || isValid(node, id),
161
+ 'ReactMount: Cached node with `%s`: %s is missing from the document. ' +
162
+ 'This probably means the DOM was unexpectedly mutated -- when removing ' +
163
+ 'React-rendered children from the DOM, rerender without those children ' +
164
+ 'or call ReactDOM.unmountComponentAtNode on the container to unmount an ' +
165
+ 'entire subtree.',
166
+ ATTR_NAME, id
167
+ );
168
+ return node;
169
+}
170
+
171
/**
172
* Finds the node with the supplied React-generated DOM ID.
173
*
@@ -165,10 +176,12 @@ function setID(node, id) {
176
* @internal
177
*/
178
function getNode(id) {
168
- if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
169
- nodeCache[id] = ReactMount.findReactNodeByID(id);
179
+ var node = getNodeIfCached(id);
180
+ if (node) {
181
+ return node;
182
+ } else {
183
+ return nodeCache[id] = ReactMount.findReactNodeByID(id);
184
}
171
- return nodeCache[id];
185
}
186
187
/**
@@ -183,10 +196,7 @@ function getNodeFromInstance(instance) {
196
if (ReactEmptyComponentRegistry.isNullComponentID(id)) {
197
return null;
198
}
186
- if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
187
- nodeCache[id] = ReactMount.findReactNodeByID(id);
188
- }
189
- return nodeCache[id];
199
+ return getNode(id);
200
}
201
202
/**
@@ -227,8 +237,8 @@ function purgeID(id) {
237
238
var deepestNodeSoFar = null;
239
function findDeepestCachedAncestorImpl(ancestorID) {
230
- var ancestor = nodeCache[ancestorID];
231
- if (ancestor && isValid(ancestor, ancestorID)) {
240
+ var ancestor = getNodeIfCached(ancestorID);
241
+ if (ancestor) {
242
deepestNodeSoFar = ancestor;
243
} else {
244
// This node isn't populated in the cache, so presumably none of its