@samitouri / QOS-React-2 / commits / db589a7175

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 }