From ed9747deedf11455ba3eb65648007ab99c26ea58 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 9 Dec 2016 18:45:34 +0000 Subject: [PATCH] Fix the bug when switching to a null portal child If pendingProps is null, we do a bailout in beginWork. This prevents unmounting of the existing child when the new child is null. We fix this by changing portal fiber's pendingProps to be the portal object itself instead of its children. This way, it is never null, and thus doesn't cause a false positive in the bailout condition. --- scripts/fiber/tests-failing.txt | 3 --- scripts/fiber/tests-passing.txt | 1 + src/renderers/shared/fiber/ReactChildFiber.js | 4 ++-- src/renderers/shared/fiber/ReactFiber.js | 2 +- src/renderers/shared/fiber/ReactFiberBeginWork.js | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/fiber/tests-failing.txt b/scripts/fiber/tests-failing.txt index 8db2ea6703..8d705c30e8 100644 --- a/scripts/fiber/tests-failing.txt +++ b/scripts/fiber/tests-failing.txt @@ -18,9 +18,6 @@ src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js src/renderers/dom/__tests__/ReactDOMProduction-test.js * should throw with an error code in production -src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js -* should reconcile portal children - src/renderers/dom/shared/__tests__/ReactDOM-test.js * throws in render() if the mount callback is not a function * throws in render() if the update callback is not a function diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 7143e78caa..6eca915bf1 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -514,6 +514,7 @@ src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js * should render one portal * should render many portals * should render nested portals +* should reconcile portal children * should keep track of namespace across portals (simple) * should keep track of namespace across portals (medium) * should keep track of namespace across portals (complex) diff --git a/src/renderers/shared/fiber/ReactChildFiber.js b/src/renderers/shared/fiber/ReactChildFiber.js index 413fd234f6..175dded7c0 100644 --- a/src/renderers/shared/fiber/ReactChildFiber.js +++ b/src/renderers/shared/fiber/ReactChildFiber.js @@ -341,7 +341,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { } else { // Update const existing = useFiber(current, priority); - existing.pendingProps = portal.children; + existing.pendingProps = portal; existing.return = returnFiber; return existing; } @@ -976,7 +976,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { ) { deleteRemainingChildren(returnFiber, child.sibling); const existing = useFiber(child, priority); - existing.pendingProps = portal.children; + existing.pendingProps = portal; existing.return = returnFiber; return existing; } else { diff --git a/src/renderers/shared/fiber/ReactFiber.js b/src/renderers/shared/fiber/ReactFiber.js index 98e47ecaab..e6badf8e93 100644 --- a/src/renderers/shared/fiber/ReactFiber.js +++ b/src/renderers/shared/fiber/ReactFiber.js @@ -346,7 +346,7 @@ exports.createFiberFromYield = function(yieldNode : ReactYield, priorityLevel : exports.createFiberFromPortal = function(portal : ReactPortal, priorityLevel : PriorityLevel) : Fiber { const fiber = createFiber(HostPortal, portal.key); - fiber.pendingProps = portal.children; + fiber.pendingProps = portal; fiber.pendingWorkPriority = priorityLevel; fiber.stateNode = { containerInfo: portal.containerInfo, diff --git a/src/renderers/shared/fiber/ReactFiberBeginWork.js b/src/renderers/shared/fiber/ReactFiberBeginWork.js index ca68c0d01b..62447db5c3 100644 --- a/src/renderers/shared/fiber/ReactFiberBeginWork.js +++ b/src/renderers/shared/fiber/ReactFiberBeginWork.js @@ -325,7 +325,7 @@ module.exports = function( function updatePortalComponent(current, workInProgress) { const priorityLevel = workInProgress.pendingWorkPriority; - const nextChildren = workInProgress.pendingProps; + const nextChildren = workInProgress.pendingProps.children; if (!current) { // Portals are special because we don't append the children during mount // but at commit. Therefore we need to track insertions which the normal