Skip to content

Commit 7feb18d

Browse files
authored
[General] Unwrap handlerData when passing event to user-defined callbacks (#3840)
## Description Due to how codegen is structured, we rely on a dynamic `handlerData` field in events so we don't have to define an event handler for each event type we may be sending. Currently, this is reflected in the API - when reading data from events, it needs to be read from `handlerData`. This PR adds flattened types and a flatten step to get rid of that step, so that data can be read directly from the event. This doesn't impact animated, so the event mapping there needs to include both `nativeEvent` and `handlerData`. ## Test plan `console.log` the events
1 parent e7eaa40 commit 7feb18d

File tree

15 files changed

+140
-85
lines changed

15 files changed

+140
-85
lines changed

packages/react-native-gesture-handler/src/components/ReanimatedDrawerLayout.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ const DrawerLayout = forwardRef<DrawerLayoutMethods, DrawerLayoutProps>(
436436
const handleRelease = useCallback(
437437
(event: PanGestureStateChangeEvent) => {
438438
'worklet';
439-
let { translationX: dragX, velocityX, x: touchX } = event.handlerData;
439+
let { translationX: dragX, velocityX, x: touchX } = event;
440440

441441
if (drawerPosition !== DrawerPosition.LEFT) {
442442
// See description in _updateAnimatedEvent about why events are flipped
@@ -550,19 +550,19 @@ const DrawerLayout = forwardRef<DrawerLayoutMethods, DrawerLayoutProps>(
550550
'worklet';
551551
const startedOutsideTranslation = isFromLeft
552552
? interpolate(
553-
event.handlerData.x,
553+
event.x,
554554
[0, drawerWidth, drawerWidth + 1],
555555
[0, drawerWidth, drawerWidth]
556556
)
557557
: interpolate(
558-
event.handlerData.x - containerWidth,
558+
event.x - containerWidth,
559559
[-drawerWidth - 1, -drawerWidth, 0],
560560
[drawerWidth, drawerWidth, 0]
561561
);
562562

563563
const startedInsideTranslation =
564564
sideCorrection *
565-
(event.handlerData.translationX +
565+
(event.translationX +
566566
(drawerOpened ? drawerWidth * -gestureOrientation : 0));
567567

568568
const adjustedTranslation = Math.max(

packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ const Swipeable = (props: SwipeableProps) => {
405405
const handleRelease = useCallback(
406406
(event: PanGestureStateChangeEvent) => {
407407
'worklet';
408-
const { velocityX } = event.handlerData;
409-
userDrag.value = event.handlerData.translationX;
408+
const { velocityX } = event;
409+
userDrag.value = event.translationX;
410410

411411
const leftThresholdProp = leftThreshold ?? leftWidth.value / 2;
412412
const rightThresholdProp = rightThreshold ?? rightWidth.value / 2;
@@ -479,14 +479,14 @@ const Swipeable = (props: SwipeableProps) => {
479479
onStart: updateElementWidths,
480480
onUpdate: (event: PanGestureUpdateEvent) => {
481481
'worklet';
482-
userDrag.value = event.handlerData.translationX;
482+
userDrag.value = event.translationX;
483483

484484
const direction =
485485
rowState.value === -1
486486
? SwipeDirection.RIGHT
487487
: rowState.value === 1
488488
? SwipeDirection.LEFT
489-
: event.handlerData.translationX > 0
489+
: event.translationX > 0
490490
? SwipeDirection.RIGHT
491491
: SwipeDirection.LEFT;
492492

packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import { ComponentClass } from 'react';
22
import { tagMessage } from '../../utils';
33
import {
44
GestureCallbacks,
5-
GestureUpdateEvent,
5+
GestureUpdateEventWithHandlerData,
66
SharedValue,
77
} from '../../v3/types';
88

99
export type ReanimatedContext<THandlerData> = {
10-
lastUpdateEvent: GestureUpdateEvent<THandlerData> | undefined;
10+
lastUpdateEvent: GestureUpdateEventWithHandlerData<THandlerData> | undefined;
1111
};
1212

1313
interface WorkletProps {

packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
22
import HostGestureDetector from '../HostGestureDetector';
33
import {
44
VirtualChild,
5-
GestureHandlerEvent,
5+
GestureHandlerEventWithHandlerData,
66
DetectorCallbacks,
77
} from '../../types';
88
import {
@@ -128,7 +128,7 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
128128

129129
const createGestureEventHandler = useCallback(
130130
(key: keyof DetectorCallbacks<THandlerData>) => {
131-
return (e: GestureHandlerEvent<THandlerData>) => {
131+
return (e: GestureHandlerEventWithHandlerData<THandlerData>) => {
132132
if (typeof gesture?.detectorCallbacks[key] === 'function') {
133133
// @ts-expect-error passing event to a union of functions where only one is typed as such
134134
gesture.detectorCallbacks[key](e);
@@ -148,12 +148,14 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
148148

149149
const getHandlers = useCallback(
150150
(key: keyof DetectorCallbacks<unknown>) => {
151-
const handlers: ((e: GestureHandlerEvent<THandlerData>) => void)[] = [];
151+
const handlers: ((
152+
e: GestureHandlerEventWithHandlerData<THandlerData>
153+
) => void)[] = [];
152154

153155
if (gesture?.detectorCallbacks[key]) {
154156
handlers.push(
155157
gesture.detectorCallbacks[key] as (
156-
e: GestureHandlerEvent<unknown>
158+
e: GestureHandlerEventWithHandlerData<unknown>
157159
) => void
158160
);
159161
}
@@ -162,7 +164,9 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
162164
const handler = child.methods[key];
163165
if (handler) {
164166
handlers.push(
165-
handler as (e: GestureHandlerEvent<THandlerData>) => void
167+
handler as (
168+
e: GestureHandlerEventWithHandlerData<THandlerData>
169+
) => void
166170
);
167171
}
168172
});

packages/react-native-gesture-handler/src/v3/hooks/callbacks/stateChangeHandler.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { CALLBACK_TYPE } from '../../../handlers/gestures/gesture';
33
import { State } from '../../../State';
44
import {
55
GestureCallbacks,
6-
GestureStateChangeEvent,
7-
StateChangeEvent,
6+
GestureStateChangeEventWithHandlerData,
7+
StateChangeEventWithHandlerData,
88
} from '../../types';
99
import {
10+
flattenEvent,
1011
isEventForHandlerWithTag,
1112
maybeExtractNativeEvent,
1213
runCallback,
@@ -17,12 +18,13 @@ export function getStateChangeHandler<THandlerData>(
1718
callbacks: GestureCallbacks<THandlerData>,
1819
context?: ReanimatedContext<THandlerData>
1920
) {
20-
return (sourceEvent: StateChangeEvent<THandlerData>) => {
21+
return (sourceEvent: StateChangeEventWithHandlerData<THandlerData>) => {
2122
'worklet';
2223

23-
const event = maybeExtractNativeEvent(
24+
const eventWithData = maybeExtractNativeEvent(
2425
sourceEvent
25-
) as GestureStateChangeEvent<THandlerData>;
26+
) as GestureStateChangeEventWithHandlerData<THandlerData>;
27+
const event = flattenEvent(eventWithData);
2628

2729
if (!isEventForHandlerWithTag(handlerTag, event)) {
2830
return;

packages/react-native-gesture-handler/src/v3/hooks/callbacks/updateHandler.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import { ReanimatedContext } from '../../../handlers/gestures/reanimatedWrapper'
44
import {
55
ChangeCalculatorType,
66
GestureCallbacks,
7-
GestureUpdateEvent,
8-
UpdateEvent,
7+
GestureUpdateEventWithHandlerData,
8+
UpdateEventWithHandlerData,
99
} from '../../types';
1010
import {
11+
flattenEvent,
1112
isEventForHandlerWithTag,
1213
maybeExtractNativeEvent,
1314
runCallback,
@@ -19,12 +20,21 @@ export function getUpdateHandler<THandlerData>(
1920
context: ReanimatedContext<THandlerData> | undefined,
2021
changeEventCalculator?: ChangeCalculatorType<THandlerData>
2122
) {
22-
return (sourceEvent: UpdateEvent<THandlerData>) => {
23+
return (sourceEvent: UpdateEventWithHandlerData<THandlerData>) => {
2324
'worklet';
2425

25-
const event = maybeExtractNativeEvent(
26+
const eventWithData = maybeExtractNativeEvent(
2627
sourceEvent
27-
) as GestureUpdateEvent<THandlerData>;
28+
) as GestureUpdateEventWithHandlerData<THandlerData>;
29+
30+
const eventWithChanges = changeEventCalculator
31+
? changeEventCalculator(
32+
eventWithData,
33+
context ? context.lastUpdateEvent : undefined
34+
)
35+
: eventWithData;
36+
37+
const event = flattenEvent(eventWithChanges);
2838

2939
if (!isEventForHandlerWithTag(handlerTag, event)) {
3040
return;
@@ -36,14 +46,8 @@ export function getUpdateHandler<THandlerData>(
3646
throw new Error(tagMessage('Event handler context is not defined'));
3747
}
3848

39-
runCallback(
40-
CALLBACK_TYPE.UPDATE,
41-
callbacks,
42-
changeEventCalculator
43-
? changeEventCalculator(event, context.lastUpdateEvent)
44-
: event
45-
);
49+
runCallback(CALLBACK_TYPE.UPDATE, callbacks, event);
4650

47-
context.lastUpdateEvent = event;
51+
context.lastUpdateEvent = eventWithData;
4852
};
4953
}

packages/react-native-gesture-handler/src/v3/hooks/callbacks/useReanimatedEventHandler.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
import {
66
ChangeCalculatorType,
77
GestureCallbacks,
8-
UnpackedGestureHandlerEvent,
8+
UnpackedGestureHandlerEventWithHandlerData,
99
} from '../../types';
1010
import { getStateChangeHandler } from './stateChangeHandler';
1111
import { getTouchEventHandler } from './touchEventHandler';
@@ -43,7 +43,9 @@ export function useReanimatedEventHandler<THandlerData>(
4343

4444
const touchCallback = getTouchEventHandler(handlerTag, handlers);
4545

46-
const callback = (event: UnpackedGestureHandlerEvent<THandlerData>) => {
46+
const callback = (
47+
event: UnpackedGestureHandlerEventWithHandlerData<THandlerData>
48+
) => {
4749
'worklet';
4850
if ('oldState' in event && event.oldState !== undefined) {
4951
stateChangeCallback(event);

packages/react-native-gesture-handler/src/v3/hooks/composition/useComposedGesture.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
2-
StateChangeEvent,
3-
UpdateEvent,
2+
StateChangeEventWithHandlerData,
3+
UpdateEventWithHandlerData,
44
TouchEvent,
55
ComposedGesture,
66
ComposedGestureName,
@@ -45,15 +45,19 @@ export function useComposedGesture(
4545
);
4646
}
4747

48-
const onGestureHandlerStateChange = (event: StateChangeEvent<unknown>) => {
48+
const onGestureHandlerStateChange = (
49+
event: StateChangeEventWithHandlerData<unknown>
50+
) => {
4951
for (const gesture of gestures) {
5052
if (gesture.detectorCallbacks.onGestureHandlerStateChange) {
5153
gesture.detectorCallbacks.onGestureHandlerStateChange(event);
5254
}
5355
}
5456
};
5557

56-
const onGestureHandlerEvent = (event: UpdateEvent<unknown>) => {
58+
const onGestureHandlerEvent = (
59+
event: UpdateEventWithHandlerData<unknown>
60+
) => {
5761
for (const gesture of gestures) {
5862
if (gesture.detectorCallbacks.onGestureHandlerEvent) {
5963
gesture.detectorCallbacks.onGestureHandlerEvent(event);

packages/react-native-gesture-handler/src/v3/hooks/useGestureCallbacks.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { useGestureStateChangeEvent } from './callbacks/js/useGestureStateChangeEvent';
22
import { useGestureUpdateEvent } from './callbacks/js/useGestureUpdateEvent';
33
import { useGestureTouchEvent } from './callbacks/js/useGestureTouchEvent';
4-
import { AnimatedEvent, BaseGestureConfig, GestureUpdateEvent } from '../types';
4+
import {
5+
AnimatedEvent,
6+
BaseGestureConfig,
7+
GestureUpdateEventWithHandlerData,
8+
} from '../types';
59
import {
610
checkMappingForChangeProperties,
711
isNativeAnimatedEvent,
@@ -82,7 +86,7 @@ export function useGestureCallbacks<THandlerData, TConfig>(
8286
}
8387

8488
let onGestureHandlerAnimatedEvent:
85-
| ((event: GestureUpdateEvent<THandlerData>) => void)
89+
| ((event: GestureUpdateEventWithHandlerData<THandlerData>) => void)
8690
| AnimatedEvent
8791
| undefined;
8892
if (config.dispatchesAnimatedEvents) {
@@ -94,6 +98,7 @@ export function useGestureCallbacks<THandlerData, TConfig>(
9498
// @ts-expect-error At this point we know it's not a native animated event, so it's callable
9599
onGestureHandlerAnimatedEvent = guardJSAnimatedEvent(config.onUpdate);
96100
} else {
101+
// @ts-expect-error The structure of an AnimatedEvent differs from other event types
97102
onGestureHandlerAnimatedEvent = config.onUpdate;
98103
}
99104
}

packages/react-native-gesture-handler/src/v3/hooks/utils/eventHandlersUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { TouchEventType } from '../../../TouchEventType';
22
import { CALLBACK_TYPE } from '../../../handlers/gestures/gesture';
33
import {
44
ChangeCalculatorType,
5-
UnpackedGestureHandlerEvent,
65
GestureCallbacks,
6+
UnpackedGestureHandlerEvent,
77
} from '../../types';
88

99
export function prepareStateChangeHandlers<THandlerData>(

0 commit comments

Comments
 (0)