Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fixtures/dom/src/components/fixtures/mouse-events/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import FixtureSet from '../../FixtureSet';
import MouseMovement from './mouse-movement';
import MouseEnter from './mouse-enter';

const React = window.React;

Expand All @@ -8,6 +9,7 @@ class MouseEvents extends React.Component {
return (
<FixtureSet title="Mouse Events">
<MouseMovement />
<MouseEnter />
</FixtureSet>
);
}
Expand Down
73 changes: 73 additions & 0 deletions fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js
Original file line number Diff line number Diff line change
@@ -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(<MouseEnterDetect />, hostEl, () => {
ReactDOM.render(<MouseEnterDetect />, hostEl.childNodes[1]);
});
}, []);

return (
<TestCase
title="Mouse Enter"
description=""
affectedBrowsers="Chrome, Safari, Firefox">
<TestCase.Steps>
<li>Mouse enter the boxes below, from different borders</li>
</TestCase.Steps>
<TestCase.ExpectedResult>
Mouse enter call count should equal to 1; <br />
Issue{' '}
<a
rel="noopener noreferrer"
target="_blank"
href="https://github.com/facebook/react/issues/16763">
#16763
</a>{' '}
should not happen.
<br />
</TestCase.ExpectedResult>
<div ref={containerRef} />
</TestCase>
);
};

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 (
<React.Fragment>
<div
ref={firstEl}
onMouseEnter={onMouseEnter}
style={{
border: '1px solid #d9d9d9',
padding: '20px 20px',
}}>
Mouse enter call count: {log.callCount || ''}
</div>
<div ref={siblingEl} />
</React.Fragment>
);
};

export default MouseEnter;
4 changes: 4 additions & 0 deletions packages/react-dom/src/events/EnterLeaveEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ const EnterLeaveEventPlugin = {

accumulateEnterLeaveDispatches(leave, enter, from, to);

if (isOutEvent && from && nativeEventTarget !== fromNode) {
return [leave];
}

return [leave, enter];
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(<MouseEnterDetect />, this.parentEl.current);
}

render() {
return <div ref={this.parentEl} />;
}
}

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 (
<React.Fragment>
<div ref={this.firstEl} onMouseEnter={mockFn} />
<div ref={this.siblingEl} />
</React.Fragment>
);
}
}

ReactDOM.render(<Parent />, container);
});
});