Skip to content

Commit 8715de8

Browse files
committed
Don't keep virtual callbacks in ref
1 parent b9abddc commit 8715de8

File tree

4 files changed

+52
-71
lines changed

4 files changed

+52
-71
lines changed

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

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import React, { useCallback, useRef, useState } from 'react';
1+
import React, { useCallback, useMemo, useState } from 'react';
22
import HostGestureDetector from '../HostGestureDetector';
33
import {
4-
VirtualChildren,
4+
VirtualChild,
55
GestureHandlerEvent,
66
DetectorCallbacks,
77
} from '../../types';
@@ -21,17 +21,24 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
2121
gesture,
2222
children,
2323
}: InterceptingGestureDetectorProps<THandlerData, TConfig>) {
24-
const [virtualChildren, setVirtualChildren] = useState<VirtualChildren[]>([]);
25-
26-
const virtualMethods = useRef<Map<number, DetectorCallbacks<unknown>>>(
27-
new Map()
24+
const [virtualChildren, setVirtualChildren] = useState<VirtualChild[]>([]);
25+
26+
const shouldUseReanimated = useMemo(
27+
() =>
28+
virtualChildren.reduce(
29+
(acc, child) => acc || child.forReanimated,
30+
gesture?.config.shouldUseReanimatedDetector ?? false
31+
),
32+
[virtualChildren, gesture]
2833
);
2934

30-
const [shouldUseReanimated, setShouldUseReanimated] = useState(
31-
gesture ? gesture.config.shouldUseReanimatedDetector : false
32-
);
33-
const [dispatchesAnimatedEvents, setDispatchesAnimatedEvents] = useState(
34-
gesture ? gesture.config.dispatchesAnimatedEvents : false
35+
const dispatchesAnimatedEvents = useMemo(
36+
() =>
37+
virtualChildren.reduce(
38+
(acc, child) => acc || child.forAnimated,
39+
gesture?.config.dispatchesAnimatedEvents ?? false
40+
),
41+
[virtualChildren, gesture]
3542
);
3643

3744
const NativeDetectorComponent = dispatchesAnimatedEvents
@@ -40,41 +47,20 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
4047
? ReanimatedNativeDetector
4148
: HostGestureDetector;
4249

43-
const register = useCallback(
44-
(
45-
child: VirtualChildren,
46-
methods: DetectorCallbacks<unknown>,
47-
forReanimated: boolean | undefined,
48-
forAnimated: boolean | undefined
49-
) => {
50-
// console.log('[IGD] Registering virtual detector', child.viewTag, child.handlerTags);
51-
setShouldUseReanimated(!!forReanimated);
52-
setDispatchesAnimatedEvents(!!forAnimated);
53-
54-
setVirtualChildren((prev) => {
55-
const index = prev.findIndex((c) => c.viewTag === child.viewTag);
56-
if (index !== -1) {
57-
const updated = [...prev];
58-
updated[index] = child;
59-
return updated;
60-
}
61-
62-
return [...prev, child];
63-
});
64-
65-
child.handlerTags.forEach((tag) => {
66-
virtualMethods.current.set(tag, methods);
67-
});
68-
},
69-
[]
70-
);
50+
const register = useCallback((child: VirtualChild) => {
51+
setVirtualChildren((prev) => {
52+
const index = prev.findIndex((c) => c.viewTag === child.viewTag);
53+
if (index !== -1) {
54+
const updated = [...prev];
55+
updated[index] = child;
56+
return updated;
57+
}
7158

72-
const unregister = useCallback((childTag: number, handlerTags: number[]) => {
73-
// console.log('[IGD] Unregistering virtual detector', childTag, handlerTags);
74-
handlerTags.forEach((tag) => {
75-
virtualMethods.current.delete(tag);
59+
return [...prev, child];
7660
});
61+
}, []);
7762

63+
const unregister = useCallback((childTag: number) => {
7864
setVirtualChildren((prev) => prev.filter((c) => c.viewTag !== childTag));
7965
}, []);
8066

@@ -93,8 +79,8 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
9379
gesture.detectorCallbacks[key](e);
9480
}
9581

96-
virtualMethods.current.forEach((callbacks) => {
97-
const method = callbacks[key];
82+
virtualChildren.forEach((child) => {
83+
const method = child.methods[key];
9884
if (method) {
9985
method(e);
10086
}
@@ -114,8 +100,8 @@ export function InterceptingGestureDetector<THandlerData, TConfig>({
114100
);
115101
}
116102

117-
virtualMethods.current.forEach((callbacks) => {
118-
const handler = callbacks[key];
103+
virtualChildren.forEach((child) => {
104+
const handler = child.methods[key];
119105
if (handler) {
120106
handlers.push(
121107
handler as (e: GestureHandlerEvent<THandlerData>) => void

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

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { isComposedGesture } from '../../hooks/utils/relationUtils';
66
import { NativeDetectorProps } from '../common';
77
import { configureRelations } from '../utils';
88
import { tagMessage } from '../../../utils';
9-
import { DetectorCallbacks } from '../../types';
9+
import { DetectorCallbacks, VirtualChild } from '../../types';
1010

1111
export function VirtualDetector<THandlerData, TConfig>(
1212
props: NativeDetectorProps<THandlerData, TConfig>
@@ -52,26 +52,20 @@ export function VirtualDetector<THandlerData, TConfig>(
5252
? props.gesture.tags
5353
: [props.gesture.tag];
5454

55-
const virtualProps = {
55+
const virtualChild: VirtualChild = {
5656
viewTag,
5757
handlerTags,
58+
methods: props.gesture.detectorCallbacks as DetectorCallbacks<unknown>,
59+
forReanimated: !!props.gesture.config.shouldUseReanimatedDetector,
60+
forAnimated: !!props.gesture.config.dispatchesAnimatedEvents,
61+
// TODO: why do we need this?
62+
viewRef: Platform.OS === 'web' ? viewRef.current : undefined,
5863
};
5964

60-
if (Platform.OS === 'web') {
61-
Object.assign(virtualProps, { viewRef });
62-
}
63-
64-
console.log('[VD] Registering virtual detector', viewTag, handlerTags);
65-
register(
66-
virtualProps,
67-
props.gesture.detectorCallbacks as DetectorCallbacks<unknown>,
68-
props.gesture.config.shouldUseReanimatedDetector,
69-
props.gesture.config.dispatchesAnimatedEvents
70-
);
65+
register(virtualChild);
7166

7267
return () => {
73-
console.log('[VD] Unregistering virtual detector', viewTag, handlerTags);
74-
unregister(viewTag, handlerTags);
68+
unregister(viewTag);
7569
};
7670
}, [viewTag, props.gesture, register, unregister]);
7771

packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/useDetectorContext.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { createContext, use } from 'react';
2-
import { DetectorCallbacks, VirtualChildren } from '../../types';
2+
import { VirtualChild } from '../../types';
33

44
type DetectorContextType = {
5-
register: (
6-
child: VirtualChildren,
7-
methods: DetectorCallbacks<unknown>,
8-
forReanimated: boolean | undefined,
9-
forAnimated: boolean | undefined
10-
) => void;
11-
unregister: (child: number, handlerTags: number[]) => void;
5+
register: (child: VirtualChild) => void;
6+
unregister: (child: number) => void;
127
};
138

149
export const DetectorContext = createContext<DetectorContextType | null>(null);

packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ export type DetectorCallbacks<THandlerData> = {
2121
onGestureHandlerAnimatedEvent: undefined | AnimatedEvent;
2222
};
2323

24-
export type VirtualChildren = {
24+
export type VirtualChild = {
2525
viewTag: number;
2626
handlerTags: number[];
27+
methods: DetectorCallbacks<unknown>;
28+
forReanimated: boolean;
29+
forAnimated: boolean;
30+
31+
// only set on web
32+
viewRef: unknown;
2733
};

0 commit comments

Comments
 (0)