Skip to content

Commit 3f058de

Browse files
authored
Event API: various bug fixes (#15485)
1 parent fb28e90 commit 3f058de

File tree

5 files changed

+93
-63
lines changed

5 files changed

+93
-63
lines changed

packages/react-dom/src/client/ReactDOMHostConfig.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,13 @@ export function handleEventTarget(
966966
rootContainerInstance: Container,
967967
internalInstanceHandle: Object,
968968
): boolean {
969+
if (
970+
__DEV__ &&
971+
type === REACT_EVENT_TARGET_TOUCH_HIT &&
972+
(props.left || props.right || props.top || props.bottom)
973+
) {
974+
return true;
975+
}
969976
return false;
970977
}
971978

@@ -992,9 +999,9 @@ export function commitEventTarget(
992999
'value of "relative".',
9931000
);
9941001
warning(
995-
computedStyles.getPropertyValue('zIndex') !== '',
1002+
computedStyles.getPropertyValue('z-index') !== '',
9961003
'<TouchHitTarget> inserts an empty <div> with "z-index" of "-1". ' +
997-
'This requires its parent DOM node to have a "z-index" great than "-1",' +
1004+
'This requires its parent DOM node to have a "z-index" greater than "-1",' +
9981005
'but the parent DOM node was found to no "z-index" value set.' +
9991006
' Try using a "z-index" value of "0" or greater.',
10001007
);

packages/react-events/src/Focus.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ const FocusResponder = {
108108
onEvent(
109109
event: ReactResponderEvent,
110110
context: ReactResponderContext,
111-
props: Object,
111+
props: FocusProps,
112112
state: FocusState,
113113
): void {
114114
const {type, target} = event;

packages/react-events/src/Press.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ const targetEventTypes = [
9494
{name: 'keydown', passive: false},
9595
{name: 'keypress', passive: false},
9696
{name: 'contextmenu', passive: false},
97-
'pointerdown',
97+
// We need to preventDefault on pointerdown for mouse/pen events
98+
// that are in hit target area but not the element area.
99+
{name: 'pointerdown', passive: false},
98100
'pointercancel',
99101
];
100102
const rootEventTypes = ['keyup', 'pointerup', 'pointermove', 'scroll'];
@@ -447,15 +449,18 @@ const PressResponder = {
447449
}
448450
}
449451

450-
// Ignore emulated mouse events and mouse pressing on touch hit target
451-
// area
452-
if (type === 'mousedown') {
453-
if (
454-
state.ignoreEmulatedMouseEvents ||
455-
isEventPositionWithinTouchHitTarget(event, context)
456-
) {
457-
return;
458-
}
452+
// Ignore emulated mouse events
453+
if (type === 'mousedown' && state.ignoreEmulatedMouseEvents) {
454+
return;
455+
}
456+
// Ignore mouse/pen pressing on touch hit target area
457+
if (
458+
(pointerType === 'mouse' || pointerType === 'pen') &&
459+
isEventPositionWithinTouchHitTarget(event, context)
460+
) {
461+
// We need to prevent the native event to block the focus
462+
nativeEvent.preventDefault();
463+
return;
459464
}
460465

461466
// Ignore any device buttons except left-mouse and touch/pen contact

packages/react-events/src/__tests__/TouchHitTarget-test.internal.js

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ describe('TouchHitTarget', () => {
318318

319319
const Test = () => (
320320
<EventComponent>
321-
<div>
321+
<div style={{position: 'relative', zIndex: 0}}>
322322
{cond ? null : (
323323
<TouchHitTarget top={10} left={10} right={10} bottom={10} />
324324
)}
@@ -330,22 +330,24 @@ describe('TouchHitTarget', () => {
330330
ReactDOM.render(<Test />, container);
331331
expect(Scheduler).toFlushWithoutYielding();
332332
expect(container.innerHTML).toBe(
333-
'<div><div style="position: absolute; z-index: -1; bottom: -10px; ' +
333+
'<div style="position: relative; z-index: 0;"><div style="position: absolute; z-index: -1; bottom: -10px; ' +
334334
'left: -10px; right: -10px; top: -10px;"></div></div>',
335335
);
336336

337337
cond = true;
338338
ReactDOM.render(<Test />, container);
339339
expect(Scheduler).toFlushWithoutYielding();
340-
expect(container.innerHTML).toBe('<div></div>');
340+
expect(container.innerHTML).toBe(
341+
'<div style="position: relative; z-index: 0;"></div>',
342+
);
341343
});
342344

343345
it('should render a conditional TouchHitTarget correctly (true -> false)', () => {
344346
let cond = true;
345347

346348
const Test = () => (
347349
<EventComponent>
348-
<div>
350+
<div style={{position: 'relative', zIndex: 0}}>
349351
{cond ? null : (
350352
<TouchHitTarget top={10} left={10} right={10} bottom={10} />
351353
)}
@@ -356,13 +358,15 @@ describe('TouchHitTarget', () => {
356358
const container = document.createElement('div');
357359
ReactDOM.render(<Test />, container);
358360
expect(Scheduler).toFlushWithoutYielding();
359-
expect(container.innerHTML).toBe('<div></div>');
361+
expect(container.innerHTML).toBe(
362+
'<div style="position: relative; z-index: 0;"></div>',
363+
);
360364

361365
cond = false;
362366
ReactDOM.render(<Test />, container);
363367
expect(Scheduler).toFlushWithoutYielding();
364368
expect(container.innerHTML).toBe(
365-
'<div><div style="position: absolute; z-index: -1; bottom: -10px; ' +
369+
'<div style="position: relative; z-index: 0;"><div style="position: absolute; z-index: -1; bottom: -10px; ' +
366370
'left: -10px; right: -10px; top: -10px;"></div></div>',
367371
);
368372
});
@@ -372,7 +376,7 @@ describe('TouchHitTarget', () => {
372376

373377
const Test = () => (
374378
<EventComponent>
375-
<div>
379+
<div style={{position: 'relative', zIndex: 0}}>
376380
{cond ? (
377381
<TouchHitTarget />
378382
) : (
@@ -386,22 +390,24 @@ describe('TouchHitTarget', () => {
386390
ReactDOM.render(<Test />, container);
387391
expect(Scheduler).toFlushWithoutYielding();
388392
expect(container.innerHTML).toBe(
389-
'<div><div style="position: absolute; z-index: -1; bottom: -10px; ' +
393+
'<div style="position: relative; z-index: 0;"><div style="position: absolute; z-index: -1; bottom: -10px; ' +
390394
'left: -10px; right: -10px; top: -10px;"></div></div>',
391395
);
392396

393397
cond = true;
394398
ReactDOM.render(<Test />, container);
395399
expect(Scheduler).toFlushWithoutYielding();
396-
expect(container.innerHTML).toBe('<div></div>');
400+
expect(container.innerHTML).toBe(
401+
'<div style="position: relative; z-index: 0;"></div>',
402+
);
397403
});
398404

399405
it('should render a conditional TouchHitTarget hit slop correctly (true -> false)', () => {
400406
let cond = true;
401407

402408
const Test = () => (
403409
<EventComponent>
404-
<div>
410+
<div style={{position: 'relative', zIndex: 0}}>
405411
<span>Random span 1</span>
406412
{cond ? (
407413
<TouchHitTarget />
@@ -417,14 +423,15 @@ describe('TouchHitTarget', () => {
417423
ReactDOM.render(<Test />, container);
418424
expect(Scheduler).toFlushWithoutYielding();
419425
expect(container.innerHTML).toBe(
420-
'<div><span>Random span 1</span><span>Random span 2</span></div>',
426+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span><span>Random span 2</span></div>',
421427
);
422428

423429
cond = false;
424430
ReactDOM.render(<Test />, container);
425431
expect(Scheduler).toFlushWithoutYielding();
426432
expect(container.innerHTML).toBe(
427-
'<div><span>Random span 1</span><div style="position: absolute; z-index: -1; bottom: -10px; ' +
433+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span>' +
434+
'<div style="position: absolute; z-index: -1; bottom: -10px; ' +
428435
'left: -10px; right: -10px; top: -10px;"></div><span>Random span 2</span></div>',
429436
);
430437
});
@@ -434,7 +441,7 @@ describe('TouchHitTarget', () => {
434441

435442
const Test = () => (
436443
<EventComponent>
437-
<div>
444+
<div style={{position: 'relative', zIndex: 0}}>
438445
<span>Random span 1</span>
439446
{cond ? (
440447
<TouchHitTarget top={10} left={null} right={10} bottom={10} />
@@ -455,15 +462,17 @@ describe('TouchHitTarget', () => {
455462
ReactDOM.render(<Test />, container);
456463
expect(Scheduler).toFlushWithoutYielding();
457464
expect(container.innerHTML).toBe(
458-
'<div><span>Random span 1</span><div style="position: absolute; z-index: -1; bottom: 0px; ' +
465+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span>' +
466+
'<div style="position: absolute; z-index: -1; bottom: 0px; ' +
459467
'left: -20px; right: 0px; top: 0px;"></div><span>Random span 2</span></div>',
460468
);
461469

462470
cond = true;
463471
ReactDOM.render(<Test />, container);
464472
expect(Scheduler).toFlushWithoutYielding();
465473
expect(container.innerHTML).toBe(
466-
'<div><span>Random span 1</span><div style="position: absolute; z-index: -1; bottom: 0px; ' +
474+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span>' +
475+
'<div style="position: absolute; z-index: -1; bottom: 0px; ' +
467476
'left: -20px; right: 0px; top: 0px;"></div><span>Random span 2</span></div>',
468477
);
469478
});
@@ -473,7 +482,7 @@ describe('TouchHitTarget', () => {
473482

474483
const Test = () => (
475484
<EventComponent>
476-
<div>
485+
<div style={{position: 'relative', zIndex: 0}}>
477486
<span>Random span 1</span>
478487
{cond ? (
479488
<TouchHitTarget top={10} left={null} right={10} bottom={10} />
@@ -494,30 +503,33 @@ describe('TouchHitTarget', () => {
494503
ReactDOM.render(<Test />, container);
495504
expect(Scheduler).toFlushWithoutYielding();
496505
expect(container.innerHTML).toBe(
497-
'<div><span>Random span 1</span><div style="position: absolute; z-index: -1; bottom: -10px; ' +
506+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span>' +
507+
'<div style="position: absolute; z-index: -1; bottom: -10px; ' +
498508
'left: 0px; right: -10px; top: -10px;"></div><span>Random span 2</span></div>',
499509
);
500510

501511
cond = false;
502512
ReactDOM.render(<Test />, container);
503513
expect(Scheduler).toFlushWithoutYielding();
504514
expect(container.innerHTML).toBe(
505-
'<div><span>Random span 1</span><div style="position: absolute; z-index: -1; bottom: -10px; ' +
515+
'<div style="position: relative; z-index: 0;"><span>Random span 1</span>' +
516+
'<div style="position: absolute; z-index: -1; bottom: -10px; ' +
506517
'left: 0px; right: -10px; top: -10px;"></div><span>Random span 2</span></div>',
507518
);
508519
});
509520

510521
it('should hydrate TouchHitTarget hit slop elements correcty and patch them', () => {
511522
const Test = () => (
512523
<EventComponent>
513-
<div>
524+
<div style={{position: 'relative', zIndex: 0}}>
514525
<TouchHitTarget top={10} left={10} right={10} bottom={10} />
515526
</div>
516527
</EventComponent>
517528
);
518529

519530
const container = document.createElement('div');
520-
container.innerHTML = '<div></div>';
531+
container.innerHTML =
532+
'<div style="position: relative; z-index: 0"></div>';
521533
expect(() => {
522534
ReactDOM.hydrate(<Test />, container);
523535
expect(Scheduler).toFlushWithoutYielding();
@@ -527,7 +539,7 @@ describe('TouchHitTarget', () => {
527539
);
528540
expect(Scheduler).toFlushWithoutYielding();
529541
expect(container.innerHTML).toBe(
530-
'<div><div style="position: absolute; z-index: -1; bottom: -10px; ' +
542+
'<div style="position: relative; z-index: 0"><div style="position: absolute; z-index: -1; bottom: -10px; ' +
531543
'left: -10px; right: -10px; top: -10px;"></div></div>',
532544
);
533545
});

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,41 @@ function commitLifeCycles(
595595
}
596596
case SuspenseComponent:
597597
case IncompleteClassComponent:
598-
case EventTarget:
599-
case EventComponent:
600-
break;
598+
return;
599+
case EventTarget: {
600+
if (enableEventAPI) {
601+
const type = finishedWork.type.type;
602+
const props = finishedWork.memoizedProps;
603+
const instance = finishedWork.stateNode;
604+
let parentInstance = null;
605+
606+
let node = finishedWork.return;
607+
// Traverse up the fiber tree until we find the parent host node.
608+
while (node !== null) {
609+
if (node.tag === HostComponent) {
610+
parentInstance = node.stateNode;
611+
break;
612+
} else if (node.tag === HostRoot) {
613+
parentInstance = node.stateNode.containerInfo;
614+
break;
615+
}
616+
node = node.return;
617+
}
618+
invariant(
619+
parentInstance !== null,
620+
'This should have a parent host component initialized. This error is likely ' +
621+
'caused by a bug in React. Please file an issue.',
622+
);
623+
commitEventTarget(type, props, instance, parentInstance);
624+
}
625+
return;
626+
}
627+
case EventComponent: {
628+
if (enableEventAPI) {
629+
mountEventComponent(finishedWork.stateNode);
630+
}
631+
return;
632+
}
601633
default: {
602634
invariant(
603635
false,
@@ -1218,31 +1250,6 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
12181250
return;
12191251
}
12201252
case EventTarget: {
1221-
if (enableEventAPI) {
1222-
const type = finishedWork.type.type;
1223-
const props = finishedWork.memoizedProps;
1224-
const instance = finishedWork.stateNode;
1225-
let parentInstance = null;
1226-
1227-
let node = finishedWork.return;
1228-
// Traverse up the fiber tree until we find the parent host node.
1229-
while (node !== null) {
1230-
if (node.tag === HostComponent) {
1231-
parentInstance = node.stateNode;
1232-
break;
1233-
} else if (node.tag === HostRoot) {
1234-
parentInstance = node.stateNode.containerInfo;
1235-
break;
1236-
}
1237-
node = node.return;
1238-
}
1239-
invariant(
1240-
parentInstance !== null,
1241-
'This should have a parent host component initialized. This error is likely ' +
1242-
'caused by a bug in React. Please file an issue.',
1243-
);
1244-
commitEventTarget(type, props, instance, parentInstance);
1245-
}
12461253
return;
12471254
}
12481255
case HostRoot: {
@@ -1259,7 +1266,6 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
12591266
return;
12601267
}
12611268
case EventComponent: {
1262-
mountEventComponent(finishedWork.stateNode);
12631269
return;
12641270
}
12651271
default: {

0 commit comments

Comments
 (0)