From 87bc7cef2c082b971a89cd68878d2b1801bfa14a Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Wed, 1 Feb 2017 18:46:06 -0800 Subject: [PATCH] Warn if unmounting a tree that was rendered by a different copy of React --- src/renderers/dom/fiber/ReactDOMFiber.js | 30 ++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/renderers/dom/fiber/ReactDOMFiber.js b/src/renderers/dom/fiber/ReactDOMFiber.js index 5a8ba571f7..65b547fb5a 100644 --- a/src/renderers/dom/fiber/ReactDOMFiber.js +++ b/src/renderers/dom/fiber/ReactDOMFiber.js @@ -108,6 +108,18 @@ function validateContainer(container) { } } +function getReactRootElementInContainer(container : any) { + if (!container) { + return null; + } + + if (container.nodeType === DOC_NODE_TYPE) { + return container.documentElement; + } else { + return container.firstChild; + } +} + function shouldAutoFocusHostComponent( type : string, props : Props, @@ -386,9 +398,12 @@ var ReactDOM = { } if (__DEV__) { + const isRootRenderedBySomeReact = Boolean(container._reactRootContainer); + const isInTreeRenderedByThisReact = ReactDOMComponentTree.getInstanceFromNode(container); + warning( - !ReactDOMComponentTree.getInstanceFromNode(container) || - container._reactRootContainer, + !isInTreeRenderedByThisReact || + isRootRenderedBySomeReact, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + @@ -427,7 +442,18 @@ var ReactDOM = { 'unmountComponentAtNode(...): Target container is not a DOM element.' ); warnAboutUnstableUse(); + if (container._reactRootContainer) { + if (__DEV__) { + const rootEl = getReactRootElementInContainer(container); + const renderedByDifferentReact = rootEl && !ReactDOMComponentTree.getInstanceFromNode(rootEl); + warning( + !renderedByDifferentReact, + 'unmountComponentAtNode(): The node you\'re attempting to unmount ' + + 'was rendered by another copy of React.' + ); + } + // Unmount should not be batched. return DOMRenderer.unbatchedUpdates(() => { return renderSubtreeIntoContainer(null, null, container, () => {