Revert "Revert "Fix createEventHandle bug with comment containers (#19348)" (#19354)"

This reverts commit 566f613763.
This commit is contained in:
Dominic Gannaway 2020-07-15 12:35:02 +01:00 committed by GitHub
parent 566f613763
commit 1099e5ee13
2 changed files with 81 additions and 2 deletions

View File

@ -22,7 +22,7 @@ import {
getEventListenerMap, getEventListenerMap,
getFiberFromScopeInstance, getFiberFromScopeInstance,
} from './ReactDOMComponentTree'; } from './ReactDOMComponentTree';
import {ELEMENT_NODE} from '../shared/HTMLNodeType'; import {ELEMENT_NODE, COMMENT_NODE} from '../shared/HTMLNodeType';
import { import {
listenToNativeEvent, listenToNativeEvent,
addEventTypeToDispatchConfig, addEventTypeToDispatchConfig,
@ -90,7 +90,7 @@ function registerEventOnNearestTargetContainer(
): void { ): void {
// If it is, find the nearest root or portal and make it // If it is, find the nearest root or portal and make it
// our event handle target container. // our event handle target container.
const targetContainer = getNearestRootOrPortalContainer(targetFiber); let targetContainer = getNearestRootOrPortalContainer(targetFiber);
if (targetContainer === null) { if (targetContainer === null) {
invariant( invariant(
false, false,
@ -98,6 +98,9 @@ function registerEventOnNearestTargetContainer(
'that did not have a corresponding root. This is likely a bug in React.', 'that did not have a corresponding root. This is likely a bug in React.',
); );
} }
if (targetContainer.nodeType === COMMENT_NODE) {
targetContainer = ((targetContainer.parentNode: any): Element);
}
const listenerMap = getEventListenerMap(targetContainer); const listenerMap = getEventListenerMap(targetContainer);
listenToNativeEvent( listenToNativeEvent(
topLevelType, topLevelType,

View File

@ -3009,6 +3009,82 @@ describe('DOMModernPluginEventSystem', () => {
expect(onClick).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledTimes(1);
}); });
// @gate experimental
it('handle propagation of click events between disjointed comment roots', () => {
const buttonRef = React.createRef();
const divRef = React.createRef();
const log = [];
const setClick = ReactDOM.unstable_createEventHandle('click');
const setClickCapture = ReactDOM.unstable_createEventHandle(
'click',
{capture: true},
);
const onClick = jest.fn(e =>
log.push(['bubble', e.currentTarget]),
);
const onClickCapture = jest.fn(e =>
log.push(['capture', e.currentTarget]),
);
function Child() {
React.useEffect(() => {
const click1 = setClick(divRef.current, onClick);
const click2 = setClickCapture(
divRef.current,
onClickCapture,
);
return () => {
click1();
click2();
};
});
return <div ref={divRef}>Click me!</div>;
}
function Parent() {
React.useEffect(() => {
const click1 = setClick(buttonRef.current, onClick);
const click2 = setClickCapture(
buttonRef.current,
onClickCapture,
);
return () => {
click1();
click2();
};
});
return <button ref={buttonRef} />;
}
// We use a comment node here, then mount to it
const disjointedNode = document.createComment(
' react-mount-point-unstable ',
);
ReactDOM.render(<Parent />, container);
Scheduler.unstable_flushAll();
buttonRef.current.appendChild(disjointedNode);
ReactDOM.render(<Child />, disjointedNode);
Scheduler.unstable_flushAll();
const buttonElement = buttonRef.current;
dispatchClickEvent(buttonElement);
expect(onClick).toHaveBeenCalledTimes(1);
expect(onClickCapture).toHaveBeenCalledTimes(1);
expect(log[0]).toEqual(['capture', buttonElement]);
expect(log[1]).toEqual(['bubble', buttonElement]);
const divElement = divRef.current;
dispatchClickEvent(divElement);
expect(onClick).toHaveBeenCalledTimes(3);
expect(onClickCapture).toHaveBeenCalledTimes(3);
expect(log[2]).toEqual(['capture', buttonElement]);
expect(log[3]).toEqual(['capture', divElement]);
expect(log[4]).toEqual(['bubble', divElement]);
expect(log[5]).toEqual(['bubble', buttonElement]);
});
}); });
}); });
}, },