From ac9dd922726b5e886cada4788cf43906f18aedf5 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Tue, 15 Oct 2013 03:21:29 +0400 Subject: [PATCH] Fix unmounting components mounted into doc element If we are to unmount a component mounted into a document element we should unmount it from document.documentElement and not from document.firstChild which is a doctype element in this specific case. --- src/core/ReactMount.js | 6 ++ .../__tests__/ReactRenderDocument-test.js | 60 +++++++++++++++++++ src/core/getReactRootElementInContainer.js | 15 ++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/core/ReactMount.js b/src/core/ReactMount.js index 217411e41b4de..29d8b626a94c8 100644 --- a/src/core/ReactMount.js +++ b/src/core/ReactMount.js @@ -430,6 +430,10 @@ var ReactMount = { unmountComponentFromNode: function(instance, container) { instance.unmountComponent(); + if (container.nodeType === DOC_NODE_TYPE) { + container = container.documentElement; + } + // http://jsperf.com/emptying-a-node while (container.lastChild) { container.removeChild(container.lastChild); @@ -592,6 +596,8 @@ var ReactMount = { ATTR_NAME: ATTR_NAME, + getReactRootID: getReactRootID, + getID: getID, setID: setID, diff --git a/src/core/__tests__/ReactRenderDocument-test.js b/src/core/__tests__/ReactRenderDocument-test.js index eec3b516da749..dd5250811ca0c 100644 --- a/src/core/__tests__/ReactRenderDocument-test.js +++ b/src/core/__tests__/ReactRenderDocument-test.js @@ -39,6 +39,66 @@ describe('rendering React components at document', function() { testDocument = getTestDocument(); }); + it('should be able to get root component id for document node', function() { + if (!testDocument) { + // These tests are not applicable in jst, since jsdom is buggy. + return; + } + + var Root = React.createClass({ + render: function() { + return ( + + + Hello World + + + Hello world + + + ); + } + }); + + ReactMount.allowFullPageRender = true; + var component = React.renderComponent(, testDocument); + expect(testDocument.body.innerHTML).toBe(' Hello world '); + + var componentID = ReactMount.getReactRootID(testDocument); + expect(componentID).toBe(component._rootNodeID); + }); + + it('should be able to unmount component from document node', function() { + if (!testDocument) { + // These tests are not applicable in jst, since jsdom is buggy. + return; + } + + var Root = React.createClass({ + render: function() { + return ( + + + Hello World + + + Hello world + + + ); + } + }); + + ReactMount.allowFullPageRender = true; + React.renderComponent(, testDocument); + expect(testDocument.body.innerHTML).toBe(' Hello world '); + + var unmounted = React.unmountComponentAtNode(testDocument); + expect(unmounted).toBe(true); + expect(testDocument.documentElement).not.toBe(null); + expect(testDocument.documentElement.innerHTML).toBe(''); + }); + it('should be able to switch root constructors via state', function() { if (!testDocument) { // These tests are not applicable in jst, since jsdom is buggy. diff --git a/src/core/getReactRootElementInContainer.js b/src/core/getReactRootElementInContainer.js index ac306a585028b..f90f5178982f1 100644 --- a/src/core/getReactRootElementInContainer.js +++ b/src/core/getReactRootElementInContainer.js @@ -18,12 +18,23 @@ "use strict"; +var DOC_NODE_TYPE = 9; + /** - * @param {DOMElement} container DOM element that may contain a React component + * @param {DOMElement|DOMDocument} container DOM element that may contain + * a React component * @return {?*} DOM element that may have the reactRoot ID, or null. */ function getReactRootElementInContainer(container) { - return container && container.firstChild; + if (!container) { + return null; + } + + if (container.nodeType === DOC_NODE_TYPE) { + return container.documentElement; + } else { + return container.firstChild; + } } module.exports = getReactRootElementInContainer;