diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts
index ab2de223cdc..70af64853c5 100644
--- a/packages/runtime-core/__tests__/hmr.spec.ts
+++ b/packages/runtime-core/__tests__/hmr.spec.ts
@@ -332,4 +332,65 @@ describe('hot module replacement', () => {
rerender(last.__hmrId!, compileToFunction(``))
expect(serializeInner(root)).toBe(`
child
`)
})
+
+ // #3302
+ test('rerender with Teleport', () => {
+ const root = nodeOps.createElement('div')
+ const target = nodeOps.createElement('div')
+ const parentId = 'parent-teleport'
+
+ const Child: ComponentOptions = {
+ data() {
+ return {
+ // style is used to ensure that the div tag will be tracked by Teleport
+ style: {},
+ target
+ }
+ },
+ render: compileToFunction(`
+
+
+
+
+
+ `)
+ }
+
+ const Parent: ComponentOptions = {
+ __hmrId: parentId,
+ components: { Child },
+ render: compileToFunction(`
+
+
+ 1
+
+
+ `)
+ }
+ createRecord(parentId, Parent)
+
+ render(h(Parent), root)
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+ expect(serializeInner(target)).toBe(``)
+
+ rerender(
+ parentId,
+ compileToFunction(`
+
+
+ 1
+ 2
+
+
+ `)
+ )
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+ expect(serializeInner(target)).toBe(
+ ``
+ )
+ })
})
diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts
index 1b51a03ac94..5bbe899e4c8 100644
--- a/packages/runtime-core/src/components/Teleport.ts
+++ b/packages/runtime-core/src/components/Teleport.ts
@@ -11,6 +11,7 @@ import {
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
import { isString, ShapeFlags } from '@vue/shared'
import { warn } from '../warning'
+import { isHmrUpdating } from '../hmr'
export type TeleportVNode = VNode
@@ -85,6 +86,13 @@ export const TeleportImpl = {
const disabled = isTeleportDisabled(n2.props)
const { shapeFlag, children } = n2
+ // #3302
+ // HMR updated, force full diff
+ if (__DEV__ && isHmrUpdating) {
+ optimized = false
+ n2.dynamicChildren = null
+ }
+
if (n1 == null) {
// insert anchors in the main view
const placeholder = (n2.el = __DEV__