Skip to content

Commit

Permalink
fix(teleport): ensure descendent component would be unmounted correct…
Browse files Browse the repository at this point in the history
…ly (#6529)

fix #6347
  • Loading branch information
nhpupu committed Oct 20, 2023
1 parent 8f0472c commit 4162311
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
25 changes: 25 additions & 0 deletions packages/runtime-core/__tests__/components/Teleport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,31 @@ describe('renderer: teleport', () => {
expect(serializeInner(target)).toBe('')
})

// #6347
test('descendent component should be unmounted when teleport is disabled and unmounted', () => {
const root = nodeOps.createElement('div')

const CompWithHook = {
render() {
return [h('p'), h('p')]
},
beforeUnmount: vi.fn(),
unmounted: vi.fn()
}

render(
h(() => [h(Teleport, { to: null, disabled: true }, h(CompWithHook))]),
root
)
expect(CompWithHook.beforeUnmount).toBeCalledTimes(0)
expect(CompWithHook.unmounted).toBeCalledTimes(0)

render(null, root)

expect(CompWithHook.beforeUnmount).toBeCalledTimes(1)
expect(CompWithHook.unmounted).toBeCalledTimes(1)
})

test('multiple teleport with same target', () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
Expand Down
29 changes: 14 additions & 15 deletions packages/runtime-core/src/components/Teleport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,27 @@ export const TeleportImpl = {
parentSuspense: SuspenseBoundary | null,
optimized: boolean,
{ um: unmount, o: { remove: hostRemove } }: RendererInternals,
doRemove: Boolean
doRemove: boolean
) {
const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode

if (target) {
hostRemove(targetAnchor!)
}

// an unmounted teleport should always remove its children if not disabled
if (doRemove || !isTeleportDisabled(props)) {
hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
for (let i = 0; i < (children as VNode[]).length; i++) {
const child = (children as VNode[])[i]
unmount(
child,
parentComponent,
parentSuspense,
true,
!!child.dynamicChildren
)
}
// an unmounted teleport should always unmount its children whether it's disabled or not
doRemove && hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
const shouldRemove = doRemove || !isTeleportDisabled(props)
for (let i = 0; i < (children as VNode[]).length; i++) {
const child = (children as VNode[])[i]
unmount(
child,
parentComponent,
parentSuspense,
shouldRemove,
!!child.dynamicChildren
)
}
}
},
Expand Down

0 comments on commit 4162311

Please sign in to comment.