From 71dcd9ed72e21a2d7f3d9345a3ab8a7dffb23bc3 Mon Sep 17 00:00:00 2001 From: Rango Yuan Date: Thu, 19 Sep 2019 23:54:20 +0800 Subject: [PATCH 1/2] Test case & fixture of mouse-enter for #16763 --- .../components/fixtures/mouse-events/index.js | 2 + .../fixtures/mouse-events/mouse-enter.js | 73 +++++++++++++++++++ .../__tests__/EnterLeaveEventPlugin-test.js | 51 +++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js diff --git a/fixtures/dom/src/components/fixtures/mouse-events/index.js b/fixtures/dom/src/components/fixtures/mouse-events/index.js index 4c121bf0947..3624d4e837b 100644 --- a/fixtures/dom/src/components/fixtures/mouse-events/index.js +++ b/fixtures/dom/src/components/fixtures/mouse-events/index.js @@ -1,5 +1,6 @@ import FixtureSet from '../../FixtureSet'; import MouseMovement from './mouse-movement'; +import MouseEnter from './mouse-enter'; const React = window.React; @@ -8,6 +9,7 @@ class MouseEvents extends React.Component { return ( + ); } diff --git a/fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js b/fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js new file mode 100644 index 00000000000..c0fbcbda6a4 --- /dev/null +++ b/fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js @@ -0,0 +1,73 @@ +import TestCase from '../../TestCase'; + +const React = window.React; +const ReactDOM = window.ReactDOM; + +const MouseEnter = () => { + const containerRef = React.useRef(); + + React.useEffect(function() { + const hostEl = containerRef.current; + ReactDOM.render(, hostEl, () => { + ReactDOM.render(, hostEl.childNodes[1]); + }); + }, []); + + return ( + + +
  • Mouse enter the boxes below, from different borders
  • +
    + + Mouse enter call count should equal to 1;
    + Issue{' '} + + #16763 + {' '} + should not happen. +
    +
    +
    + + ); +}; + +const MouseEnterDetect = () => { + const [log, setLog] = React.useState({}); + const firstEl = React.useRef(); + const siblingEl = React.useRef(); + + const onMouseEnter = e => { + const timeStamp = e.timeStamp; + setLog(log => { + const callCount = 1 + (log.timeStamp === timeStamp ? log.callCount : 0); + return { + timeStamp, + callCount, + }; + }); + }; + + return ( + +
    + Mouse enter call count: {log.callCount || ''} +
    +
    + + ); +}; + +export default MouseEnter; diff --git a/packages/react-dom/src/events/__tests__/EnterLeaveEventPlugin-test.js b/packages/react-dom/src/events/__tests__/EnterLeaveEventPlugin-test.js index 33dd3e964ee..b8bda1c67fe 100644 --- a/packages/react-dom/src/events/__tests__/EnterLeaveEventPlugin-test.js +++ b/packages/react-dom/src/events/__tests__/EnterLeaveEventPlugin-test.js @@ -134,4 +134,55 @@ describe('EnterLeaveEventPlugin', () => { expect(childEnterCalls).toBe(1); expect(parentEnterCalls).toBe(0); }); + + // Test for https://github.com/facebook/react/issues/16763. + it('should call mouseEnter once from sibling rendered inside a rendered component', done => { + const mockFn = jest.fn(); + + class Parent extends React.Component { + constructor(props) { + super(props); + this.parentEl = React.createRef(); + } + + componentDidMount() { + ReactDOM.render(, this.parentEl.current); + } + + render() { + return
    ; + } + } + + class MouseEnterDetect extends React.Component { + constructor(props) { + super(props); + this.firstEl = React.createRef(); + this.siblingEl = React.createRef(); + } + + componentDidMount() { + this.siblingEl.current.dispatchEvent( + new MouseEvent('mouseout', { + bubbles: true, + cancelable: true, + relatedTarget: this.firstEl.current, + }), + ); + expect(mockFn.mock.calls.length).toBe(1); + done(); + } + + render() { + return ( + +
    +
    + + ); + } + } + + ReactDOM.render(, container); + }); }); From 3fed177cbd73631847ee58a5af803e339a96f894 Mon Sep 17 00:00:00 2001 From: Rango Yuan Date: Fri, 27 Sep 2019 23:03:47 +0800 Subject: [PATCH 2/2] fix - fire mouseenter event handlers twice --- packages/react-dom/src/events/EnterLeaveEventPlugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-dom/src/events/EnterLeaveEventPlugin.js b/packages/react-dom/src/events/EnterLeaveEventPlugin.js index 41330064881..aca14122528 100644 --- a/packages/react-dom/src/events/EnterLeaveEventPlugin.js +++ b/packages/react-dom/src/events/EnterLeaveEventPlugin.js @@ -146,6 +146,10 @@ const EnterLeaveEventPlugin = { accumulateEnterLeaveDispatches(leave, enter, from, to); + if (isOutEvent && from && nativeEventTarget !== fromNode) { + return [leave]; + } + return [leave, enter]; }, };