diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index ba9c7c0780b..3f157d009a9 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -851,4 +851,47 @@ describe('hot module replacement', () => { expect(serializeInner(root)).toBe(`
1
1
`) }) + + test('reload async child wrapped in Suspense + KeepAlive', async () => { + const id = 'async-child-reload' + const AsyncChild: ComponentOptions = { + __hmrId: id, + async setup() { + await nextTick() + return () => 'foo' + }, + } + createRecord(id, AsyncChild) + + const appId = 'test-app-id' + const App: ComponentOptions = { + __hmrId: appId, + components: { AsyncChild }, + render: compileToFunction(` +
+ + + + + +
+ `), + } + + const root = nodeOps.createElement('div') + render(h(App), root) + expect(serializeInner(root)).toBe('
') + await timeout() + expect(serializeInner(root)).toBe('
foo
') + + reload(id, { + __hmrId: id, + async setup() { + await nextTick() + return () => 'bar' + }, + }) + await timeout() + expect(serializeInner(root)).toBe('
bar
') + }) }) diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index 0adf4fd4329..7aedf52dd3e 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -144,7 +144,9 @@ function reload(id: string, newComp: HMRComponent): void { // components to be unmounted and re-mounted. Queue the update so that we // don't end up forcing the same parent to re-render multiple times. queueJob(() => { + isHmrUpdating = true instance.parent!.update() + isHmrUpdating = false // #6930, #11248 avoid infinite recursion dirtyInstances.delete(instance) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 9b50dca23f9..90cc22f5470 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1211,6 +1211,9 @@ function baseCreateRenderer( // setup() is async. This component relies on async logic to be resolved // before proceeding if (__FEATURE_SUSPENSE__ && instance.asyncDep) { + // avoid hydration for hmr updating + if (__DEV__ && isHmrUpdating) initialVNode.el = null + parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect, optimized)