diff --git a/packages/jsx/src/index.test.tsx b/packages/jsx/src/index.test.tsx
index 8564f111..c8ea4fed 100644
--- a/packages/jsx/src/index.test.tsx
+++ b/packages/jsx/src/index.test.tsx
@@ -399,4 +399,31 @@ test('ref unmount callback', async () => {
assert.is(ref, null)
})
+test('child ref unmount callback', async () => {
+ const { h, hf, parent, mount, window } = setup()
+
+ const Component = (props: JSX.HTMLAttributes) =>
+
+ let ref: null | HTMLElement = null
+
+ const component = (
+ {
+ ref = el
+ return () => {
+ ref = null
+ }
+ }}
+ />
+ )
+
+ mount(parent, component)
+ assert.instance(ref, window.HTMLElement)
+ await sleep()
+
+ ref!.remove()
+ await sleep()
+ assert.is(ref, null)
+})
+
test.run()
diff --git a/packages/jsx/src/index.ts b/packages/jsx/src/index.ts
index 350bd039..e1c05dcf 100644
--- a/packages/jsx/src/index.ts
+++ b/packages/jsx/src/index.ts
@@ -155,7 +155,11 @@ export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => {
if (k === 'ref') {
ctx.schedule(() => {
const cleanup = prop(ctx, element)
- if (typeof cleanup === 'function') unlink(element, cleanup)
+ if (typeof cleanup === 'function') {
+ let list = unsubscribesMap.get(element)
+ if (!list) unsubscribesMap.set(element, (list = []))
+ unlink(element, cleanup)
+ }
})
} else if (isAtom(prop) && !prop.__reatom.isAction) {
if (k.startsWith('model:')) {