diff --git a/packages/react-dom/src/events/DOMModernPluginEventSystem.js b/packages/react-dom/src/events/DOMModernPluginEventSystem.js index 095e1b6ce8..03ecd50ade 100644 --- a/packages/react-dom/src/events/DOMModernPluginEventSystem.js +++ b/packages/react-dom/src/events/DOMModernPluginEventSystem.js @@ -417,13 +417,13 @@ export function dispatchEventForPluginEventSystem( // sub-tree for that root and make that our ancestor instance. let node = targetInst; - while (true) { + mainLoop: while (true) { if (node === null) { return; } const nodeTag = node.tag; if (nodeTag === HostRoot || nodeTag === HostPortal) { - const container = node.stateNode.containerInfo; + let container = node.stateNode.containerInfo; if (isMatchingRootContainer(container, targetContainerNode)) { break; } @@ -449,18 +449,23 @@ export function dispatchEventForPluginEventSystem( grandNode = grandNode.return; } } - const parentSubtreeInst = getClosestInstanceFromNode(container); - if (parentSubtreeInst === null) { - return; + // Now we need to find it's corresponding host fiber in the other + // tree. To do this we can use getClosestInstanceFromNode, but we + // need to validate that the fiber is a host instance, otherwise + // we need to traverse up through the DOM till we find the correct + // node that is from the other tree. + while (container !== null) { + const parentNode = getClosestInstanceFromNode(container); + if (parentNode === null) { + return; + } + const parentTag = parentNode.tag; + if (parentTag === HostComponent || parentTag === HostText) { + node = ancestorInst = parentNode; + continue mainLoop; + } + container = container.parentNode; } - const parentTag = parentSubtreeInst.tag; - // getClosestInstanceFromNode can return a HostRoot or SuspenseComponent. - // So we need to ensure we only set the ancestor to a HostComponent or HostText. - if (parentTag === HostComponent || parentTag === HostText) { - ancestorInst = parentSubtreeInst; - } - node = parentSubtreeInst; - continue; } node = node.return; } diff --git a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js index 538353fff4..a690b574e9 100644 --- a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js +++ b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js @@ -224,6 +224,95 @@ describe('DOMModernPluginEventSystem', () => { expect(log[5]).toEqual(['bubble', buttonElement]); }); + it('handle propagation of click events between disjointed roots #2', () => { + const buttonRef = React.createRef(); + const button2Ref = React.createRef(); + const divRef = React.createRef(); + const spanRef = React.createRef(); + const log = []; + const onClick = jest.fn(e => log.push(['bubble', e.currentTarget])); + const onClickCapture = jest.fn(e => + log.push(['capture', e.currentTarget]), + ); + + function Child() { + return ( +