Experiemental event API - wrap async dispatched events (#15299)
Dominic Gannaway committed
Apr 3, 2019 at 10:25 UTC
38fa84088a4ef0347a89ee176a501c2c2ee8ea96
3 files changed
+50
-39
packages/events/EventTypes.js
+1
@@ -39,4 +39,5 @@ export type EventResponderContext = {
39
) => void,
40
requestOwnership: (target: Element | Document | null) => boolean,
41
releaseOwnership: (target: Element | Document | null) => boolean,
42
+ withAsyncDispatching: (func: () => void) => void,
43
};
packages/react-dom/src/events/DOMEventResponderSystem.js
+15
-14
@@ -58,19 +58,13 @@ type EventQueue = {
58
bubble: null | Array<$Shape<PartialEventObject>>,
59
capture: null | Array<$Shape<PartialEventObject>>,
60
discrete: boolean,
61
- phase: EventQueuePhase,
61
};
63
-type EventQueuePhase = 0 | 1;
62
65
-const DURING_EVENT_PHASE = 0;
66
-const AFTER_EVENT_PHASE = 1;
67
-
68
-function createEventQueue(phase: EventQueuePhase): EventQueue {
63
+function createEventQueue(): EventQueue {
64
return {
65
bubble: null,
66
capture: null,
67
discrete: false,
73
- phase,
68
};
69
}
70
@@ -134,7 +128,7 @@ function DOMEventResponderContext(
128
this._discreteEvents = null;
129
this._nonDiscreteEvents = null;
130
this._isBatching = true;
137
- this._eventQueue = createEventQueue(DURING_EVENT_PHASE);
131
+ this._eventQueue = createEventQueue();
132
}
133
134
DOMEventResponderContext.prototype.isPassive = function(): boolean {
@@ -203,9 +197,6 @@ DOMEventResponderContext.prototype.dispatchEvent = function(
197
if (stopPropagation) {
198
eventsWithStopPropagation.add(eventObject);
199
}
206
- if (eventQueue.phase === AFTER_EVENT_PHASE) {
207
- batchedUpdates(processEventQueue, eventQueue);
208
- }
200
};
201
202
DOMEventResponderContext.prototype.isTargetWithinEventComponent = function(
@@ -320,6 +311,19 @@ DOMEventResponderContext.prototype.releaseOwnership = function(
311
return false;
312
};
313
314
+DOMEventResponderContext.prototype.withAsyncDispatching = function(
315
+ func: () => void,
316
+) {
317
+ const previousEventQueue = this._eventQueue;
318
+ this._eventQueue = createEventQueue();
319
+ try {
320
+ func();
321
+ batchedUpdates(processEventQueue, this._eventQueue);
322
+ } finally {
323
+ this._eventQueue = previousEventQueue;
324
+ }
325
+};
326
+
327
function getTargetEventTypes(
328
eventTypes: Array<ReactEventResponderEventType>,
329
): Set<DOMTopLevelEventType> {
@@ -401,8 +405,5 @@ export function runResponderEventsInBatch(
405
}
406
}
407
processEventQueue(context._eventQueue);
404
- // In order to capture and process async events from responder modules
405
- // we create a new event queue.
406
- context._eventQueue = createEventQueue(AFTER_EVENT_PHASE);
408
}
409
}
packages/react-events/src/Press.js
+34
-25
@@ -118,33 +118,42 @@ function dispatchPressStartEvents(
118
DEFAULT_LONG_PRESS_DELAY_MS,
119
);
120
121
- state.longPressTimeout = setTimeout(() => {
122
- state.isLongPressed = true;
123
- state.longPressTimeout = null;
121
+ state.longPressTimeout = setTimeout(
122
+ () =>
123
+ context.withAsyncDispatching(() => {
124
+ state.isLongPressed = true;
125
+ state.longPressTimeout = null;
126
125
- if (props.onLongPress) {
126
- const longPressEventListener = e => {
127
- props.onLongPress(e);
128
- // TODO address this again at some point
129
- // if (e.nativeEvent.defaultPrevented) {
130
- // state.defaultPrevented = true;
131
- // }
132
- };
133
- dispatchPressEvent(context, state, 'longpress', longPressEventListener);
134
- }
127
+ if (props.onLongPress) {
128
+ const longPressEventListener = e => {
129
+ props.onLongPress(e);
130
+ // TODO address this again at some point
131
+ // if (e.nativeEvent.defaultPrevented) {
132
+ // state.defaultPrevented = true;
133
+ // }
134
+ };
135
+ dispatchPressEvent(
136
+ context,
137
+ state,
138
+ 'longpress',
139
+ longPressEventListener,
140
+ );
141
+ }
142
136
- if (props.onLongPressChange) {
137
- const longPressChangeEventListener = () => {
138
- props.onLongPressChange(true);
139
- };
140
- dispatchPressEvent(
141
- context,
142
- state,
143
- 'longpresschange',
144
- longPressChangeEventListener,
145
- );
146
- }
147
- }, delayLongPress);
143
+ if (props.onLongPressChange) {
144
+ const longPressChangeEventListener = () => {
145
+ props.onLongPressChange(true);
146
+ };
147
+ dispatchPressEvent(
148
+ context,
149
+ state,
150
+ 'longpresschange',
151
+ longPressChangeEventListener,
152
+ );
153
+ }
154
+ }),
155
+ delayLongPress,
156
+ );
157
}
158
}
159