diff --git a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts
index 799108dca8a..62aebd1a995 100644
--- a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts
+++ b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts
@@ -1,4 +1,5 @@
import {
+ Suspense,
defineComponent,
h,
nextTick,
@@ -537,4 +538,39 @@ describe('api: template refs', () => {
'
[object Object],[object Object]
',
)
})
+
+ it('with async component', async () => {
+ const deps: Promise[] = []
+ const spy = vi.fn()
+
+ const AsyncChild = defineComponent({
+ async setup(_, { expose }) {
+ const p = new Promise(r => setTimeout(r, 1))
+ deps.push(p.then(() => Promise.resolve()))
+ await p
+ expose({ foo: spy })
+ return () => h('div', 'child')
+ },
+ })
+
+ const childRef = ref(null)
+ const App = {
+ setup() {
+ return { refKey: childRef }
+ },
+ render() {
+ return h(Suspense, null, { default: h(AsyncChild, { ref: 'refKey' }) })
+ },
+ }
+
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+
+ await Promise.all(deps)
+ await nextTick()
+
+ expect((childRef.value as any).foo).toBe(spy)
+ ;(childRef.value as any).foo()
+ expect(spy).toBeCalledTimes(1)
+ })
})
diff --git a/packages/runtime-core/src/rendererTemplateRef.ts b/packages/runtime-core/src/rendererTemplateRef.ts
index 1ffe3035794..c6da0b14a60 100644
--- a/packages/runtime-core/src/rendererTemplateRef.ts
+++ b/packages/runtime-core/src/rendererTemplateRef.ts
@@ -28,6 +28,13 @@ export function setRef(
vnode: VNode,
isUnmount = false,
): void {
+ if (parentSuspense) {
+ queuePostRenderEffect(() => {
+ setRef(rawRef, oldRawRef, null, vnode, isUnmount)
+ }, parentSuspense)
+ return
+ }
+
if (isArray(rawRef)) {
rawRef.forEach((r, i) =>
setRef(