Skip to content

Commit 00c7223

Browse files
committed
fix(hmr): avoid errors when updating KeepAlive slot component (#7042)
1 parent f67bb50 commit 00c7223

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,44 @@ describe('hot module replacement', () => {
151151
expect(mountSpy).toHaveBeenCalledTimes(1)
152152
})
153153

154+
test('reload KeepAlive slot', async () => {
155+
const root = nodeOps.createElement('div')
156+
const childId = 'test-child-keep-alive'
157+
const unmountSpy = jest.fn()
158+
const mountSpy = jest.fn()
159+
160+
const Child: ComponentOptions = {
161+
__hmrId: childId,
162+
data() {
163+
return { count: 0 }
164+
},
165+
unmounted: unmountSpy,
166+
render: compileToFunction(`<div>{{ count }}</div>`)
167+
}
168+
createRecord(childId, Child)
169+
170+
const Parent: ComponentOptions = {
171+
components: { Child },
172+
render: compileToFunction(`<KeepAlive><Child/></KeepAlive>`)
173+
}
174+
175+
render(h(Parent), root)
176+
expect(serializeInner(root)).toBe(`<div>0</div>`)
177+
178+
reload(childId, {
179+
__hmrId: childId,
180+
data() {
181+
return { count: 1 }
182+
},
183+
mounted: mountSpy,
184+
render: compileToFunction(`<div>{{ count }}</div>`)
185+
})
186+
await nextTick()
187+
expect(serializeInner(root)).toBe(`<div>1</div>`)
188+
expect(unmountSpy).toHaveBeenCalledTimes(1)
189+
expect(mountSpy).toHaveBeenCalledTimes(1)
190+
})
191+
154192
test('reload class component', async () => {
155193
const root = nodeOps.createElement('div')
156194
const childId = 'test4-child'

packages/runtime-core/src/vnode.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
352352
n2.shapeFlag & ShapeFlags.COMPONENT &&
353353
hmrDirtyComponents.has(n2.type as ConcreteComponent)
354354
) {
355+
// #7042, ensure the vnode being unmounted during HMR
356+
if (n1.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
357+
n1.shapeFlag -= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
358+
}
359+
// #7042, ensure the vnode being mounted as fresh during HMR
360+
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
361+
n2.shapeFlag -= ShapeFlags.COMPONENT_KEPT_ALIVE
362+
}
355363
// HMR only: if the component has been hot-updated, force a reload.
356364
return false
357365
}

0 commit comments

Comments
 (0)