@@ -73,7 +73,6 @@ import {
7373 enableUseEventAPI ,
7474 enableScopeAPI ,
7575} from 'shared/ReactFeatureFlags' ;
76- import { HostComponent } from 'react-reconciler/src/ReactWorkTags' ;
7776import {
7877 RESPONDER_EVENT_SYSTEM ,
7978 IS_PASSIVE ,
@@ -95,6 +94,10 @@ import {
9594import { getListenerMapForElement } from '../events/DOMEventListenerMap' ;
9695import { TOP_BEFORE_BLUR , TOP_AFTER_BLUR } from '../events/DOMTopLevelEventTypes' ;
9796
97+ // TODO: This is an exposed internal, we should move this around
98+ // so this isn't the case.
99+ import { isFiberInsideHiddenOrRemovedTree } from 'react-reconciler/src/ReactFiberTreeReflection' ;
100+
98101export type ReactListenerEvent = ReactDOMListenerEvent ;
99102export type ReactListenerMap = ReactDOMListenerMap ;
100103export type ReactListener = ReactDOMListener ;
@@ -250,6 +253,15 @@ export function getPublicInstance(instance: Instance): * {
250253export function prepareForCommit ( containerInfo : Container ) : void {
251254 eventsEnabled = ReactBrowserEventEmitterIsEnabled ( ) ;
252255 selectionInformation = getSelectionInformation ( ) ;
256+ if ( enableDeprecatedFlareAPI || enableUseEventAPI ) {
257+ const focusedElem = selectionInformation . focusedElem ;
258+ if ( focusedElem !== null ) {
259+ const instance = getClosestInstanceFromNode ( focusedElem ) ;
260+ if ( instance !== null && isFiberInsideHiddenOrRemovedTree ( instance ) ) {
261+ dispatchBeforeDetachedBlur ( focusedElem ) ;
262+ }
263+ }
264+ }
253265 ReactBrowserEventEmitterSetEnabled ( false ) ;
254266}
255267
@@ -532,18 +544,11 @@ function dispatchBeforeDetachedBlur(target: HTMLElement): void {
532544 ) ;
533545 }
534546 if ( enableUseEventAPI ) {
535- try {
536- // We need to temporarily enable the event system
537- // to dispatch the "beforeblur" event.
538- ReactBrowserEventEmitterSetEnabled ( true ) ;
539- const event = createEvent ( TOP_BEFORE_BLUR ) ;
540- // Dispatch "beforeblur" directly on the target,
541- // so it gets picked up by the event system and
542- // can propagate through the React internal tree.
543- target . dispatchEvent ( event ) ;
544- } finally {
545- ReactBrowserEventEmitterSetEnabled ( false ) ;
546- }
547+ const event = createEvent ( TOP_BEFORE_BLUR ) ;
548+ // Dispatch "beforeblur" directly on the target,
549+ // so it gets picked up by the event system and
550+ // can propagate through the React internal tree.
551+ target . dispatchEvent ( event ) ;
547552 }
548553}
549554
@@ -571,20 +576,9 @@ function dispatchAfterDetachedBlur(target: HTMLElement): void {
571576 }
572577}
573578
574- // This is a specific event for the React Flare
575- // event system, so event responders can act
576- // accordingly to a DOM node being unmounted that
577- // previously had active document focus.
578579export function beforeRemoveInstance (
579580 instance : Instance | TextInstance | SuspenseInstance ,
580581) : void {
581- if (
582- ( enableDeprecatedFlareAPI || enableUseEventAPI ) &&
583- selectionInformation &&
584- instance === selectionInformation . focusedElem
585- ) {
586- dispatchBeforeDetachedBlur ( ( ( instance : any ) : HTMLElement ) ) ;
587- }
588582 if ( enableUseEventAPI ) {
589583 // It's unfortunate that we have to do this cleanup, but
590584 // it's necessary otherwise we will leak the host instances
@@ -674,28 +668,7 @@ export function clearSuspenseBoundaryFromContainer(
674668 retryIfBlockedOn ( container ) ;
675669}
676670
677- function instanceContainsElem ( instance : Instance , element : HTMLElement ) {
678- let fiber = getClosestInstanceFromNode ( element ) ;
679- while ( fiber !== null ) {
680- if ( fiber . tag === HostComponent && fiber . stateNode === instance ) {
681- return true ;
682- }
683- fiber = fiber . return ;
684- }
685- return false ;
686- }
687-
688671export function hideInstance ( instance : Instance ) : void {
689- // Ensure we trigger `onBeforeBlur` if the active focused elment
690- // is ether the instance of a child or the instance. We need
691- // to traverse the Fiber tree here rather than use node.contains()
692- // as the child node might be inside a Portal.
693- if ( ( enableDeprecatedFlareAPI || enableUseEventAPI ) && selectionInformation ) {
694- const focusedElem = selectionInformation . focusedElem ;
695- if ( focusedElem !== null && instanceContainsElem ( instance , focusedElem ) ) {
696- dispatchBeforeDetachedBlur ( ( ( focusedElem : any ) : HTMLElement ) ) ;
697- }
698- }
699672 // TODO: Does this work for all element types? What about MathML? Should we
700673 // pass host context to this method?
701674 instance = ( ( instance : any ) : HTMLElement ) ;
0 commit comments