react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
113 lines (99 loc) • 3.05 kB
text/typescript
import { useEffect, useMemo } from 'react';
import { getNextHandlerTag } from '../../handlers/getNextHandlerTag';
import {
registerGesture,
unregisterGesture,
} from '../../handlers/handlersRegistry';
import { scheduleFlushOperations } from '../../handlers/utils';
import { tagMessage } from '../../utils';
import { NativeProxy } from '../NativeProxy';
import type {
BaseGestureConfig,
SingleGesture,
SingleGestureName,
} from '../types';
import { useGestureCallbacks } from './useGestureCallbacks';
import {
bindSharedValues,
prepareConfigForNativeSide,
prepareRelations,
unbindSharedValues,
} from './utils';
export function useGesture<
TConfig,
THandlerData,
TExtendedHandlerData extends THandlerData = THandlerData,
>(
type: SingleGestureName,
config: BaseGestureConfig<TConfig, THandlerData, TExtendedHandlerData>
): SingleGesture<TConfig, THandlerData, TExtendedHandlerData> {
const handlerTag = useMemo(() => getNextHandlerTag(), []);
const disableReanimated = useMemo(() => config.disableReanimated, []);
if (config.disableReanimated !== disableReanimated) {
throw new Error(
tagMessage(
'The "disableReanimated" property must not be changed after the handler is created.'
)
);
}
// TODO: Call only necessary hooks depending on which callbacks are defined (?)
const { jsEventHandler, reanimatedEventHandler, animatedEventHandler } =
useGestureCallbacks(handlerTag, config);
if (config.shouldUseReanimatedDetector && !reanimatedEventHandler) {
throw new Error(tagMessage('Failed to create reanimated event handlers.'));
}
const gestureRelations = useMemo(
() =>
prepareRelations(
{
simultaneousWith: config.simultaneousWith,
requireToFail: config.requireToFail,
block: config.block,
},
handlerTag
),
[handlerTag, config.simultaneousWith, config.requireToFail, config.block]
);
const gesture = useMemo(
() => ({
handlerTag,
type,
config,
detectorCallbacks: {
jsEventHandler,
animatedEventHandler,
reanimatedEventHandler,
},
gestureRelations,
}),
[
handlerTag,
type,
config,
jsEventHandler,
reanimatedEventHandler,
animatedEventHandler,
gestureRelations,
]
);
useEffect(() => {
NativeProxy.createGestureHandler(type, handlerTag, {});
scheduleFlushOperations();
return () => {
NativeProxy.dropGestureHandler(handlerTag);
scheduleFlushOperations();
};
}, [type, handlerTag]);
useEffect(() => {
const preparedConfig = prepareConfigForNativeSide(type, config);
NativeProxy.setGestureHandlerConfig(handlerTag, preparedConfig);
scheduleFlushOperations();
bindSharedValues(config, handlerTag);
registerGesture(handlerTag, gesture);
return () => {
unbindSharedValues(config, handlerTag);
unregisterGesture(handlerTag);
};
}, [handlerTag, config, type, gesture]);
return gesture;
}