diff --git a/src/renderers/shared/fiber/ReactChildFiber.js b/src/renderers/shared/fiber/ReactChildFiber.js index af4af15404566..f51a00ba011e4 100644 --- a/src/renderers/shared/fiber/ReactChildFiber.js +++ b/src/renderers/shared/fiber/ReactChildFiber.js @@ -508,6 +508,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { // boolean, undefined, etc. break; } + if (shouldTrackSideEffects) { + if (oldFiber && !newFiber.alternate) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); if (!previousNewFiber) { // TODO: Move out of the loop. This only happens for the first run. @@ -573,7 +580,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { // it from the child list so that we don't add it to the deletion // list. existingChildren.delete( - newFiber.key === null ? newFiber.index : newFiber.key + newFiber.key === null ? newIdx : newFiber.key ); } } diff --git a/src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js b/src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js index 897422d2274d2..ab8f7a55d7cba 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js @@ -164,6 +164,124 @@ describe('ReactIncrementalSideEffects', () => { }); + it('can delete a child that changes type - implicit keys', function() { + + let unmounted = false; + + class ClassComponent extends React.Component { + componentWillUnmount() { + unmounted = true; + } + render() { + return ; + } + } + + function FunctionalComponent(props) { + return ; + } + + function Foo(props) { + return ( +