From 1ce9ff31aef0c96ea6f9ffedba7e29042dd6e539 Mon Sep 17 00:00:00 2001 From: Gdhanush_13 Date: Thu, 9 Apr 2026 12:20:56 +0530 Subject: [PATCH] fix(useId): prevent FinalizationRegistry leak on every re-render registry.register() was called unconditionally in the render body, adding a new entry on every render. Since FinalizationRegistry.register() always adds a new entry (even with the same target), this leaked entries until the component unmounted. Fix: track the last registered id in a ref and only call register() when the id changes. Unregister the previous entry before re-registering. Fixes #9852 --- packages/react-aria/src/utils/useId.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-aria/src/utils/useId.ts b/packages/react-aria/src/utils/useId.ts index 693f3ba901e..daf8886540a 100644 --- a/packages/react-aria/src/utils/useId.ts +++ b/packages/react-aria/src/utils/useId.ts @@ -43,9 +43,14 @@ export function useId(defaultId?: string): string { let res = useSSRSafeId(value); let cleanupRef = useRef(null); + let registeredId = useRef(null); - if (registry) { + if (registry && registeredId.current !== res) { + if (registeredId.current !== null) { + registry.unregister(cleanupRef); + } registry.register(cleanupRef, res); + registeredId.current = res; } if (canUseDOM) { @@ -65,6 +70,7 @@ export function useId(defaultId?: string): string { if (registry) { registry.unregister(cleanupRef); } + registeredId.current = null; idsUpdaterMap.delete(r); }; }, [res]);