Preserve DOM node when updating empty component
Fixes #2770.
Ben Alpert committed
Sep 9, 2015 at 13:57 UTC
db589a717510d1a2d235d934a0eec4b5609b4e0b
3 files changed
+39
-13
src/renderers/shared/reconciler/ReactChildReconciler.js
+2
-1
@@ -90,7 +90,8 @@ var ReactChildReconciler = {
90
var prevChild = prevChildren && prevChildren[name];
91
var prevElement = prevChild && prevChild._currentElement;
92
var nextElement = nextChildren[name];
93
- if (shouldUpdateReactComponent(prevElement, nextElement)) {
93
+ if (prevChild != null &&
94
+ shouldUpdateReactComponent(prevElement, nextElement)) {
95
ReactReconciler.receiveComponent(
96
prevChild, nextElement, transaction, context
97
);
src/renderers/shared/reconciler/__tests__/ReactEmptyComponent-test.js
+21
@@ -265,4 +265,25 @@ describe('ReactEmptyComponent', function() {
265
ReactTestUtils.renderIntoDocument(<Parent />);
266
}).not.toThrow();
267
});
268
+
269
+ it('preserves the dom node during updates', function() {
270
+ var Empty = React.createClass({
271
+ render: function() {
272
+ return null;
273
+ },
274
+ });
275
+
276
+ var container = document.createElement('div');
277
+
278
+ ReactDOM.render(<Empty />, container);
279
+ var noscript1 = container.firstChild;
280
+ expect(noscript1.tagName).toBe('NOSCRIPT');
281
+
282
+ // This update shouldn't create a DOM node
283
+ ReactDOM.render(<Empty />, container);
284
+ var noscript2 = container.firstChild;
285
+ expect(noscript2.tagName).toBe('NOSCRIPT');
286
+
287
+ expect(noscript1).toBe(noscript2);
288
+ });
289
});
src/renderers/shared/reconciler/shouldUpdateReactComponent.js
+16
-12
@@ -24,18 +24,22 @@
24
* @protected
25
*/
26
function shouldUpdateReactComponent(prevElement, nextElement) {
27
- if (prevElement != null && nextElement != null) {
28
- var prevType = typeof prevElement;
29
- var nextType = typeof nextElement;
30
- if (prevType === 'string' || prevType === 'number') {
31
- return (nextType === 'string' || nextType === 'number');
32
- } else {
33
- return (
34
- nextType === 'object' &&
35
- prevElement.type === nextElement.type &&
36
- prevElement.key === nextElement.key
37
- );
38
- }
27
+ var prevEmpty = prevElement === null || prevElement === false;
28
+ var nextEmpty = nextElement === null || nextElement === false;
29
+ if (prevEmpty || nextEmpty) {
30
+ return prevEmpty === nextEmpty;
31
+ }
32
+
33
+ var prevType = typeof prevElement;
34
+ var nextType = typeof nextElement;
35
+ if (prevType === 'string' || prevType === 'number') {
36
+ return (nextType === 'string' || nextType === 'number');
37
+ } else {
38
+ return (
39
+ nextType === 'object' &&
40
+ prevElement.type === nextElement.type &&
41
+ prevElement.key === nextElement.key
42
+ );
43
}
44
return false;
45
}