Skip to content

Commit 10a2c60

Browse files
authoredSep 13, 2024··
fix(hmr): reload async child wrapped in Suspense + KeepAlive (#11907)
close #11868
1 parent f2d8019 commit 10a2c60

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed
 

‎packages/runtime-core/__tests__/hmr.spec.ts

+43
Original file line numberDiff line numberDiff line change
@@ -851,4 +851,47 @@ describe('hot module replacement', () => {
851851

852852
expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>`)
853853
})
854+
855+
test('reload async child wrapped in Suspense + KeepAlive', async () => {
856+
const id = 'async-child-reload'
857+
const AsyncChild: ComponentOptions = {
858+
__hmrId: id,
859+
async setup() {
860+
await nextTick()
861+
return () => 'foo'
862+
},
863+
}
864+
createRecord(id, AsyncChild)
865+
866+
const appId = 'test-app-id'
867+
const App: ComponentOptions = {
868+
__hmrId: appId,
869+
components: { AsyncChild },
870+
render: compileToFunction(`
871+
<div>
872+
<Suspense>
873+
<KeepAlive>
874+
<AsyncChild />
875+
</KeepAlive>
876+
</Suspense>
877+
</div>
878+
`),
879+
}
880+
881+
const root = nodeOps.createElement('div')
882+
render(h(App), root)
883+
expect(serializeInner(root)).toBe('<div><!----></div>')
884+
await timeout()
885+
expect(serializeInner(root)).toBe('<div>foo</div>')
886+
887+
reload(id, {
888+
__hmrId: id,
889+
async setup() {
890+
await nextTick()
891+
return () => 'bar'
892+
},
893+
})
894+
await timeout()
895+
expect(serializeInner(root)).toBe('<div>bar</div>')
896+
})
854897
})

‎packages/runtime-core/src/hmr.ts

+2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ function reload(id: string, newComp: HMRComponent): void {
144144
// components to be unmounted and re-mounted. Queue the update so that we
145145
// don't end up forcing the same parent to re-render multiple times.
146146
queueJob(() => {
147+
isHmrUpdating = true
147148
instance.parent!.update()
149+
isHmrUpdating = false
148150
// #6930, #11248 avoid infinite recursion
149151
dirtyInstances.delete(instance)
150152
})

‎packages/runtime-core/src/renderer.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,9 @@ function baseCreateRenderer(
12111211
// setup() is async. This component relies on async logic to be resolved
12121212
// before proceeding
12131213
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
1214+
// avoid hydration for hmr updating
1215+
if (__DEV__ && isHmrUpdating) initialVNode.el = null
1216+
12141217
parentSuspense &&
12151218
parentSuspense.registerDep(instance, setupRenderEffect, optimized)
12161219

0 commit comments

Comments
 (0)
Please sign in to comment.