diff --git a/packages/fluentui/CHANGELOG.md b/packages/fluentui/CHANGELOG.md index 8592947e55db76..d6be7edc0623b4 100644 --- a/packages/fluentui/CHANGELOG.md +++ b/packages/fluentui/CHANGELOG.md @@ -76,6 +76,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix RadioGroup visual issues. Add `RadioButtonIcon`. Fix vertical RadioGroup alignment issue with custom content. Fix focus frame alignment for bare indicator. @TanelVari ([#16478](https://github.com/microsoft/fluentui/pull/16478)) - Fix type for `Accessibility` to allow function without props @ling1726 ([#16322](https://github.com/microsoft/fluentui/pull/16322)) - Optimize `NumberListIcon` for bundled size @ling1726 ([#16473](https://github.com/microsoft/fluentui/pull/16473)) +- Fix event handlers behavior and compatibility with portals in React 17 @layershifter ([#16514](https://github.com/microsoft/fluentui/pull/16514)) ### Features - Add 2.0 light and dark themes @jurokapsiar ([#15867](https://github.com/microsoft/fluentui/pull/15867)) diff --git a/packages/fluentui/react-component-event-listener/src/useEventListener.ts b/packages/fluentui/react-component-event-listener/src/useEventListener.ts index 6b53ad7fc86e0a..ee2b9b397b090e 100644 --- a/packages/fluentui/react-component-event-listener/src/useEventListener.ts +++ b/packages/fluentui/react-component-event-listener/src/useEventListener.ts @@ -35,8 +35,23 @@ export const useEventListener = (options: EventListenerOpt React.useEffect(() => { const element: Target | null | undefined = typeof targetRef === 'undefined' ? target : targetRef.current; + // Store the current event to avoid triggering handlers immediately + // Note this depends on a deprecated but extremely well supported quirk of the web platform + // https://github.com/facebook/react/issues/20074 + let currentEvent = window.event; + + const conditionalHandler = (event: DocumentEventMap[T]) => { + // Skip if this event is the same as the one running when we added the handlers + if (event === currentEvent) { + currentEvent = undefined; + return; + } + + eventHandler(event); + }; + if (isActionSupported(element, 'addEventListener')) { - element.addEventListener(type, eventHandler, capture); + element.addEventListener(type, conditionalHandler, capture); } else if (process.env.NODE_ENV !== 'production') { throw new Error( '@fluentui/react-component-event-listener: Passed `element` is not valid or does not support `addEventListener()` method.', @@ -45,7 +60,7 @@ export const useEventListener = (options: EventListenerOpt return () => { if (isActionSupported(element, 'removeEventListener')) { - element.removeEventListener(type, eventHandler, capture); + element.removeEventListener(type, conditionalHandler, capture); } else if (process.env.NODE_ENV !== 'production') { throw new Error( '@fluentui/react-component-event-listener: Passed `element` is not valid or does not support `removeEventListener()` method.',