fix(hmr): reload async child wrapped in Suspense + KeepAlive (#11907)

close #11868
This commit is contained in:
edison 2024-09-13 20:19:47 +08:00 committed by GitHub
parent f2d8019188
commit 10a2c6053b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 0 deletions

View File

@ -851,4 +851,47 @@ describe('hot module replacement', () => {
expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>`)
})
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(`
<div>
<Suspense>
<KeepAlive>
<AsyncChild />
</KeepAlive>
</Suspense>
</div>
`),
}
const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe('<div><!----></div>')
await timeout()
expect(serializeInner(root)).toBe('<div>foo</div>')
reload(id, {
__hmrId: id,
async setup() {
await nextTick()
return () => 'bar'
},
})
await timeout()
expect(serializeInner(root)).toBe('<div>bar</div>')
})
})

View File

@ -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)
})

View File

@ -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)