Skip to content

Commit

Permalink
Event API: ensure preventDefault works for nested targets (#15633)
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm authored May 13, 2019
1 parent edfedf3 commit fec74f9
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
22 changes: 22 additions & 0 deletions packages/react-dom/src/events/DOMEventResponderSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ const eventResponderContext: ReactResponderContext = {
childTarget: Element | Document,
parentTarget: Element | Document,
): boolean {
validateResponderContext();
const childFiber = getClosestInstanceFromNode(childTarget);
const parentFiber = getClosestInstanceFromNode(parentTarget);

Expand Down Expand Up @@ -345,6 +346,7 @@ const eventResponderContext: ReactResponderContext = {
}
},
getFocusableElementsInScope(): Array<HTMLElement> {
validateResponderContext();
const focusableElements = [];
const eventComponentInstance = ((currentInstance: any): ReactEventComponentInstance);
let node = ((eventComponentInstance.currentFiber: any): Fiber).child;
Expand Down Expand Up @@ -383,6 +385,7 @@ const eventResponderContext: ReactResponderContext = {
getEventPointerType(
event: ReactResponderEvent,
): '' | 'mouse' | 'keyboard' | 'pen' | 'touch' {
validateResponderContext();
const nativeEvent: any = event.nativeEvent;
const {type, pointerType} = nativeEvent;
if (pointerType != null) {
Expand All @@ -400,6 +403,7 @@ const eventResponderContext: ReactResponderContext = {
return '';
},
getEventCurrentTarget(event: ReactResponderEvent): Element {
validateResponderContext();
const target: any = event.target;
let currentTarget = target;
while (
Expand All @@ -412,8 +416,26 @@ const eventResponderContext: ReactResponderContext = {
return currentTarget;
},
getTimeStamp(): number {
validateResponderContext();
return currentTimeStamp;
},
isTargetWithinHostComponent(
target: Element | Document,
elementType: string,
): boolean {
validateResponderContext();
let fiber = getClosestInstanceFromNode(target);
while (fiber !== null) {
if (fiber.stateNode === currentInstance) {
return false;
}
if (fiber.tag === HostComponent && fiber.type === elementType) {
return true;
}
fiber = fiber.return;
}
return false;
},
};

function isTargetWithinEventComponent(target: Element | Document): boolean {
Expand Down
6 changes: 1 addition & 5 deletions packages/react-events/src/Press.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,6 @@ function dispatchCancel(
}
}

function isAnchorTagElement(eventTarget: EventTarget): boolean {
return (eventTarget: any).nodeName === 'A';
}

function isValidKeyPress(key: string): boolean {
// Accessibility for keyboards. Space and Enter only.
return key === ' ' || key === 'Enter';
Expand Down Expand Up @@ -673,7 +669,7 @@ const PressResponder = {
}

case 'click': {
if (isAnchorTagElement(target)) {
if (context.isTargetWithinHostComponent(target, 'a')) {
const {
altKey,
ctrlKey,
Expand Down
19 changes: 19 additions & 0 deletions packages/react-events/src/__tests__/Press-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -1965,6 +1965,25 @@ describe('Event responder: Press', () => {
expect(preventDefault).toBeCalled();
});

it('prevents native behaviour by default with nested elements', () => {
const onPress = jest.fn();
const preventDefault = jest.fn();
const ref = React.createRef();
const element = (
<Press onPress={onPress}>
<a href="#">
<div ref={ref} />
</a>
</Press>
);
ReactDOM.render(element, container);

ref.current.dispatchEvent(createEvent('pointerdown'));
ref.current.dispatchEvent(createEvent('pointerup'));
ref.current.dispatchEvent(createEvent('click', {preventDefault}));
expect(preventDefault).toBeCalled();
});

it('uses native behaviour for interactions with modifier keys', () => {
const onPress = jest.fn();
const preventDefault = jest.fn();
Expand Down
4 changes: 4 additions & 0 deletions packages/shared/ReactTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,8 @@ export type ReactResponderContext = {
): '' | 'mouse' | 'keyboard' | 'pen' | 'touch',
getEventCurrentTarget(event: ReactResponderEvent): Element,
getTimeStamp: () => number,
isTargetWithinHostComponent: (
target: Element | Document,
elementType: string,
) => boolean,
};

0 comments on commit fec74f9

Please sign in to comment.