Skip to content

Commit

Permalink
Add more non-React events to the priority list (#20774)
Browse files Browse the repository at this point in the history
* Add a test for mouseover being continuous

* Add more non-React events to the priority list
  • Loading branch information
gaearon authored Feb 9, 2021
1 parent d919e2c commit ad8211d
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let React;

let ReactDOM;
let Scheduler;
let act;

describe('ReactDOMNativeEventHeuristic-test', () => {
let container;
Expand All @@ -23,6 +24,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
React = require('react');
ReactDOM = require('react-dom');
Scheduler = require('scheduler');
act = require('react-dom/test-utils').unstable_concurrentAct;

document.body.appendChild(container);
});
Expand Down Expand Up @@ -225,4 +227,68 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
// Therefore the form should have been submitted.
expect(formSubmitted).toBe(true);
});

// @gate experimental
// @gate enableDiscreteEventMicroTasks && enableNativeEventPriorityInference
it('mouse over should be user-blocking but not discrete', async () => {
const root = ReactDOM.unstable_createRoot(container);

const target = React.createRef(null);
function Foo() {
const [isHover, setHover] = React.useState(false);
React.useLayoutEffect(() => {
target.current.onmouseover = () => setHover(true);
});
return <div ref={target}>{isHover ? 'hovered' : 'not hovered'}</div>;
}

await act(async () => {
root.render(<Foo />);
});
expect(container.textContent).toEqual('not hovered');

await act(async () => {
const mouseOverEvent = document.createEvent('MouseEvents');
mouseOverEvent.initEvent('mouseover', true, true);
dispatchAndSetCurrentEvent(target.current, mouseOverEvent);

// 3s should be enough to expire the updates
Scheduler.unstable_advanceTime(3000);
expect(Scheduler).toFlushExpired([]);
expect(container.textContent).toEqual('hovered');
});
});

// @gate experimental
// @gate enableDiscreteEventMicroTasks && enableNativeEventPriorityInference
it('mouse enter should be user-blocking but not discrete', async () => {
const root = ReactDOM.unstable_createRoot(container);

const target = React.createRef(null);
function Foo() {
const [isHover, setHover] = React.useState(false);
React.useLayoutEffect(() => {
target.current.onmouseenter = () => setHover(true);
});
return <div ref={target}>{isHover ? 'hovered' : 'not hovered'}</div>;
}

await act(async () => {
root.render(<Foo />);
});
expect(container.textContent).toEqual('not hovered');

await act(async () => {
// Note: React does not use native mouseenter/mouseleave events
// but we should still correctly determine their priority.
const mouseEnterEvent = document.createEvent('MouseEvents');
mouseEnterEvent.initEvent('mouseenter', true, true);
dispatchAndSetCurrentEvent(target.current, mouseEnterEvent);

// 3s should be enough to expire the updates
Scheduler.unstable_advanceTime(3000);
expect(Scheduler).toFlushExpired([]);
expect(container.textContent).toEqual('hovered');
});
});
});
10 changes: 10 additions & 0 deletions packages/react-dom/src/events/DOMEventNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export type DOMEventName =
// 'animationend |
// 'animationstart' |
| 'beforeblur' // Not a real event. This is used by event experiments.
| 'beforeinput'
| 'blur'
| 'canplay'
| 'canplaythrough'
| 'cancel'
Expand Down Expand Up @@ -44,9 +46,12 @@ export type DOMEventName =
| 'encrypted'
| 'ended'
| 'error'
| 'focus'
| 'focusin'
| 'focusout'
| 'fullscreenchange'
| 'gotpointercapture'
| 'hashchange'
| 'input'
| 'invalid'
| 'keydown'
Expand All @@ -58,6 +63,8 @@ export type DOMEventName =
| 'loadedmetadata'
| 'lostpointercapture'
| 'mousedown'
| 'mouseenter'
| 'mouseleave'
| 'mousemove'
| 'mouseout'
| 'mouseover'
Expand All @@ -74,12 +81,15 @@ export type DOMEventName =
| 'pointerout'
| 'pointerover'
| 'pointerup'
| 'popstate'
| 'progress'
| 'ratechange'
| 'reset'
| 'scroll'
| 'seeked'
| 'seeking'
| 'select'
| 'selectstart'
| 'selectionchange'
| 'stalled'
| 'submit'
Expand Down
14 changes: 14 additions & 0 deletions packages/react-dom/src/events/ReactDOMEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,16 @@ export function getEventPriority(domEventName: DOMEventName): * {
// eslint-disable-next-line no-fallthrough
case 'beforeblur':
case 'afterblur':
// Not used by React but could be by user code:
// eslint-disable-next-line no-fallthrough
case 'beforeinput':
case 'blur':
case 'fullscreenchange':
case 'focus':
case 'hashchange':
case 'popstate':
case 'select':
case 'selectstart':
return InputDiscreteLanePriority;
case 'drag':
case 'dragenter':
Expand All @@ -413,6 +423,10 @@ export function getEventPriority(domEventName: DOMEventName): * {
case 'toggle':
case 'touchmove':
case 'wheel':
// Not used by React but could be by user code:
// eslint-disable-next-line no-fallthrough
case 'mouseenter':
case 'mouseleave':
return InputContinuousLanePriority;
default:
return DefaultLanePriority;
Expand Down

0 comments on commit ad8211d

Please sign in to comment.