diff --git a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js index 1b92c0ff53..86ddbbff30 100644 --- a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js @@ -595,7 +595,8 @@ describe('ReactDOMEventListener', () => { const container = document.createElement('div'); const innerRef = React.createRef(); const outerRef = React.createRef(); - const onPlayCapture = jest.fn(); + const onPlayCapture = jest.fn(e => log.push(e.currentTarget)); + const log = []; document.body.appendChild(container); try { ReactDOM.render( @@ -612,12 +613,23 @@ describe('ReactDOMEventListener', () => { }), ); expect(onPlayCapture).toHaveBeenCalledTimes(3); + expect(log).toEqual([ + outerRef.current, + outerRef.current.firstChild, + innerRef.current, + ]); outerRef.current.dispatchEvent( new Event('play', { bubbles: false, }), ); expect(onPlayCapture).toHaveBeenCalledTimes(4); + expect(log).toEqual([ + outerRef.current, + outerRef.current.firstChild, + innerRef.current, + outerRef.current, + ]); } finally { document.body.removeChild(container); } diff --git a/packages/react-dom/src/events/DOMPluginEventSystem.js b/packages/react-dom/src/events/DOMPluginEventSystem.js index 161f3931df..3083031fd3 100644 --- a/packages/react-dom/src/events/DOMPluginEventSystem.js +++ b/packages/react-dom/src/events/DOMPluginEventSystem.js @@ -718,9 +718,6 @@ export function accumulateSinglePhaseListeners( const captured = bubbled !== null ? bubbled + 'Capture' : null; const listeners: Array = []; - // If we are not handling EventTarget only phase, then we're doing the - // usual two phase accumulation using the React fiber tree to pick up - // all relevant useEvent and on* prop events. let instance = targetFiber; let lastHostComponent = null; const targetType = event.type; diff --git a/packages/react-dom/src/events/plugins/SimpleEventPlugin.js b/packages/react-dom/src/events/plugins/SimpleEventPlugin.js index a09d2d7bc7..641e8a4ed9 100644 --- a/packages/react-dom/src/events/plugins/SimpleEventPlugin.js +++ b/packages/react-dom/src/events/plugins/SimpleEventPlugin.js @@ -43,6 +43,7 @@ import getEventCharCode from '../getEventCharCode'; import {IS_CAPTURE_PHASE, IS_NON_DELEGATED} from '../EventSystemFlags'; import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags'; +import {getClosestInstanceFromNode} from '../../client/ReactDOMComponentTree'; function extractEvents( dispatchQueue: DispatchQueue, @@ -174,6 +175,13 @@ function extractEvents( // TODO: We may also want to re-use the accumulateTargetOnly flag to // special case bubbling for onScroll/media events at a later point. const accumulateTargetOnly = inCapturePhase && isNonDelegatedEvent; + // If we are not handling accumulateTargetOnly, then we should traverse + // through all React fiber tree, finding all relevant useEvent and + // on* prop events as we traverse the tree. Otherwise, we should + // only handle the target fiber and stop traversal straight after. + if (accumulateTargetOnly) { + targetInst = getClosestInstanceFromNode(((targetContainer: any): Node)); + } // We traverse only capture or bubble phase listeners accumulateSinglePhaseListeners(