From aa282dadb56651033c9c60c11fe41908ea41c172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikolas=20Schr=C3=B6ter?= <25958801+nwidynski@users.noreply.github.com> Date: Sun, 26 Oct 2025 12:36:23 +0100 Subject: [PATCH 1/3] feat: support modern useEffectEvent --- packages/@react-aria/utils/src/useEffectEvent.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/@react-aria/utils/src/useEffectEvent.ts b/packages/@react-aria/utils/src/useEffectEvent.ts index 20b89d03038..e1496198b0b 100644 --- a/packages/@react-aria/utils/src/useEffectEvent.ts +++ b/packages/@react-aria/utils/src/useEffectEvent.ts @@ -17,7 +17,10 @@ import {useLayoutEffect} from './useLayoutEffect'; // before all layout effects, but is available only in React 18 and later. const useEarlyEffect = React['useInsertionEffect'] ?? useLayoutEffect; -export function useEffectEvent(fn?: T): T { +// Starting with React 19.2, this hook has been internalized. +const useModernEffectEvent = React['useEffectEvent'] ?? useLegacyEffectEvent; + +function useLegacyEffectEvent(fn?: T): T { const ref = useRef(null); useEarlyEffect(() => { ref.current = fn; @@ -28,3 +31,8 @@ export function useEffectEvent(fn?: T): T { return f?.(...args); }, []); } + +export function useEffectEvent(fn?: T): T { + let noop = useCallback(() => {}, []); + return useModernEffectEvent(fn ?? noop); +} From 58b2af9ea018323d21c680e0ac17bc7abee30f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikolas=20Schr=C3=B6ter?= <25958801+nwidynski@users.noreply.github.com> Date: Sun, 26 Oct 2025 22:10:33 +0100 Subject: [PATCH 2/3] chore: require callback --- packages/@react-aria/utils/src/useEffectEvent.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@react-aria/utils/src/useEffectEvent.ts b/packages/@react-aria/utils/src/useEffectEvent.ts index e1496198b0b..f5046d525d3 100644 --- a/packages/@react-aria/utils/src/useEffectEvent.ts +++ b/packages/@react-aria/utils/src/useEffectEvent.ts @@ -32,7 +32,6 @@ function useLegacyEffectEvent(fn?: T): T { }, []); } -export function useEffectEvent(fn?: T): T { - let noop = useCallback(() => {}, []); - return useModernEffectEvent(fn ?? noop); +export function useEffectEvent(fn: T): T { + return useModernEffectEvent(fn); } From 672e8eed47a030071a89bc4f4313db5243b45598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikolas=20Schr=C3=B6ter?= <25958801+nwidynski@users.noreply.github.com> Date: Mon, 27 Oct 2025 12:43:38 +0100 Subject: [PATCH 3/3] fix: backwards compatibility --- packages/@react-aria/utils/src/useEvent.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/utils/src/useEvent.ts b/packages/@react-aria/utils/src/useEvent.ts index 1dd35499847..c83b479e614 100644 --- a/packages/@react-aria/utils/src/useEvent.ts +++ b/packages/@react-aria/utils/src/useEvent.ts @@ -11,7 +11,7 @@ */ import {RefObject} from '@react-types/shared'; -import {useEffect} from 'react'; +import {useCallback, useEffect} from 'react'; import {useEffectEvent} from './useEffectEvent'; export function useEvent( @@ -20,7 +20,8 @@ export function useEvent( handler?: (this: Document, ev: GlobalEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions ): void { - let handleEvent = useEffectEvent(handler); + let noop = useCallback(() => {}, []); + let handleEvent = useEffectEvent(handler ?? noop); let isDisabled = handler == null; useEffect(() => {