Skip to content

Commit

Permalink
fix(hmr): reload async child wrapped in Suspense + KeepAlive (#11907)
Browse files Browse the repository at this point in the history
close #11868
  • Loading branch information
edison1105 authored Sep 13, 2024
1 parent f2d8019 commit 10a2c60
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
43 changes: 43 additions & 0 deletions packages/runtime-core/__tests__/hmr.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>')
})
})
2 changes: 2 additions & 0 deletions packages/runtime-core/src/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down
3 changes: 3 additions & 0 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down

0 comments on commit 10a2c60

Please sign in to comment.