diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts
index 3f157d009..01feb91ac 100644
--- a/packages/runtime-core/__tests__/hmr.spec.ts
+++ b/packages/runtime-core/__tests__/hmr.spec.ts
@@ -894,4 +894,47 @@ describe('hot module replacement', () => {
await timeout()
expect(serializeInner(root)).toBe('
bar
')
})
+
+ test('rerender for nested component', () => {
+ const id = 'child-nested-rerender'
+ const Foo: ComponentOptions = {
+ __hmrId: id,
+ render() {
+ return this.$slots.default()
+ },
+ }
+ createRecord(id, Foo)
+
+ const parentId = 'parent-nested-rerender'
+ const Parent: ComponentOptions = {
+ __hmrId: parentId,
+ render() {
+ return h(Foo, null, {
+ default: () => this.$slots.default(),
+ _: 3 /* FORWARDED */,
+ })
+ },
+ }
+
+ const appId = 'app-nested-rerender'
+ const App: ComponentOptions = {
+ __hmrId: appId,
+ render: () =>
+ h(Parent, null, {
+ default: () => [
+ h(Foo, null, {
+ default: () => ['foo'],
+ }),
+ ],
+ }),
+ }
+ createRecord(parentId, App)
+
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+ expect(serializeInner(root)).toBe('foo')
+
+ rerender(id, () => 'bar')
+ expect(serializeInner(root)).toBe('bar')
+ })
})
diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts
index 7aedf52dd..2c46ea73b 100644
--- a/packages/runtime-core/src/hmr.ts
+++ b/packages/runtime-core/src/hmr.ts
@@ -7,7 +7,7 @@ import {
type InternalRenderFunction,
isClassComponent,
} from './component'
-import { queueJob, queuePostFlushCb } from './scheduler'
+import { SchedulerJobFlags, queueJob, queuePostFlushCb } from './scheduler'
import { extend, getGlobalThis } from '@vue/shared'
type HMRComponent = ComponentOptions | ClassComponent
@@ -96,7 +96,10 @@ function rerender(id: string, newRender?: Function): void {
instance.renderCache = []
// this flag forces child components with slot content to update
isHmrUpdating = true
- instance.update()
+ // #13771 don't update if the job is already disposed
+ if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {
+ instance.update()
+ }
isHmrUpdating = false
})
}