0

I'm about to swap the old React Native Animated library with the new React Native Reanimated one to gain performance issues but I have encountered one problem I could not solve.

In all examples I found online, I saw that the GestureHandler, created with useAnimatedGestureHandler, is in the same component as the Animated.View. In reality that is sometimes not possible.

In my previous app, I just pass the GestureHandler object to the component via forwardRef but it seems React Native Reanimated is not able to do that. I don't know whether I have a syntax error or it is just a bug.

const App = () => {
  const handlerRef = useAnimatedRef();
  const y = useSharedValue(0);

  handlerRef.current = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startY = y.value;
    },
    onActive: ({translationX, translationY}, ctx) => {
      y.value = translationY;
    },
    onEnd: () => {},
  });

  const animatedStyles = useAnimatedStyle(() => ({transform: [{translateY: withSpring(y.value)}]}));

  const UsingHandlerDirect = () => (
    <PanGestureHandler onGestureEvent={handlerRef.current} >
      <Animated.View style={[styles.blueBox, animatedStyles]} />
    </PanGestureHandler>
  )

  const UsingHandlerForwardRef = forwardRef(({animatedStyles}, ref) => (
    <PanGestureHandler onGestureEvent={ref?.handlerRef?.current}>
      <Animated.View style={[styles.redBox, animatedStyles]} />
    </PanGestureHandler>
  ));

  return (
    <SafeAreaView>
      <View style={styles.container}>
        <UsingHandlerForwardRef ref={handlerRef} animatedStyles={animatedStyles}/>
        <UsingHandlerDirect />
      </View>
    </SafeAreaView>
  );
}

I have saved the GestureHandler in a useAnimatedRef handlerRef.current = useAnimatedGestureHandler({}) to make things more representable. Then I pass the the ref directly into the PanGestureHandler of the UsingHandlerDirect component. The result is that when I drag the blue box the box will follow the handler. So this version works.

But as soon as I pass the handlerRef to the UsingHandlerForwardRef component non of the gesture events get fired. I would expect that when I drag the red box will also follow the handler but it doesn't

Has someone an idea whether it's me or it's a bug in the library?

Cheers

Thomas Dittmar
  • 1,764
  • 1
  • 23
  • 42

1 Answers1

0

I have given up on the idea to pass a ref around instead, I created a hook that connects both components with each other via context.

I created a simple hook


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

const useAppState = () => {
  const sharedXValue = useSharedValue(0);

  return {
    sharedXValue,
  };
};

export default useAppState;

that holds the shared value using useSharedValue from reanimated 2

The child component uses this value in the gestureHandler like that


const gestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startX = sharedXValue.value;
    },
    onActive: (event, ctx) => {
      sharedXValue.value = ctx.startX + event.translationX;
    },
    onEnd: (_) => {
      sharedXValue.value = withSpring(0);
    },
  });

and the Parent just consumes the hook value

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

I have created a workable Snack which contains the 2 components - a Child with a blue box and a Parent with a red box

Thomas Dittmar
  • 1,764
  • 1
  • 23
  • 42