Home > database >  GestureDetector gesture handler app crash when calling external function
GestureDetector gesture handler app crash when calling external function

Time:09-29

i tried to use GestureDetector of react-native-gesture-handler

import React from 'react';
import { Directions, Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';

/**
 * Component used as Home Page
 */
const HomePage: React.FC  = () => {
  const position = useSharedValue(0);
  const trigger = () => {
    console.log('fdfs')
  }

  const flingGesture = Gesture.Fling()
    .direction(Directions.RIGHT)
    .onStart((e) => {
      position.value = withTiming(position.value   10, { duration: 100 });
      console.log(e)
      // trigger()
    });

    const flingGestureLeft = Gesture.Fling()
    .direction(Directions.LEFT)
    .onStart((e) => {
      position.value = withTiming(position.value - 10, { duration: 100 });
      // trigger()
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: position.value }],
  }));

  return (
    <GestureDetector gesture={Gesture.Simultaneous(flingGestureLeft, flingGesture)}>
      <Animated.View style={[{ width: 100, height: 30, backgroundColor: 'red' }, animatedStyle]} />
    </GestureDetector>
  );
}

export default HomePage;

this work without problem when i fling my bloc to left or right, but when i tried to call an exeternal function like the trigger(), my app crash. Is a bug of the gesture detector or there is something to add?

CodePudding user response:

The reanimated, gesture handler hooks and callbacks works on the UI thread and the trigger function you defined is by default on the JS thread, so you can not use it directly.

There are two solutions to this:

  1. add 'worklet' in the trigger function as below
    const trigger = () => {
      'worklet'
      console.log('fdfs')
    }
  1. Or wrap your function with 'runOnJS' from reanimated as below

    import { runOnJS } from 'react-native-reanimated';

    const flingGesture = Gesture.Fling()
      .direction(Directions.RIGHT)
      .onStart((e) => {
        position.value = withTiming(position.value   10, { duration: 100 });
        console.log(e)
        runOnJS(trigger)()
      });

Note:- syntax for runOnJS is like 'runOnJS(functionName)(params). So if your function takes two params (Ex. 1st number and 2nd string), you would call it like this:- runOnJS(trigger)(1, 'dummyString')

For more details you can read the docs from reanimated and gesture-handler.

  • Related