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.
This commit is contained in:
Dan Abramov
2016-12-09 18:45:37 +00:00
parent 3f2129aeee
commit ed9747deed
5 changed files with 5 additions and 7 deletions
-3
View File
@@ -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
+1
View File
@@ -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)
@@ -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 {
+1 -1
View File
@@ -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,
@@ -325,7 +325,7 @@ module.exports = function<T, P, I, TI, C, CX>(
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