通过 forwardRef 传递 useAnimatedGestureHandler

Pass useAnimatedGestureHandler via forwardRef

我准备将旧的 React Native Animated 库替换为新的 React Native Reanimated 库以解决性能问题,但我遇到了一个我无法解决的问题。

在我在网上找到的所有示例中,我看到使用 useAnimatedGestureHandler 创建的 GestureHandlerAnimated.View 在同一组件中。事实上,有时这是不可能的。

在我以前的应用程序中,我只是通过 forwardRefGestureHandler 对象传递给组件,但似乎 React Native Reanimated 无法做到这一点。不知道是语法错误还是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>
  );
}

我已将 GestureHandler 保存在 useAnimatedRef handlerRef.current = useAnimatedGestureHandler({}) 中,以使事情更具代表性。然后我将 ref 直接传递到 UsingHandlerDirect 组件的 PanGestureHandler 中。结果是,当我拖动蓝色框时,框将跟随处理程序。所以这个版本有效。

但是一旦我将 handlerRef 传递给 UsingHandlerForwardRef 组件,就不会触发任何手势事件。我希望当我拖动红色框时也会跟随处理程序但它不会

有人知道是我的问题还是库中的错误吗?

干杯

我放弃了传递 ref 的想法,而是创建了一个钩子,通过上下文将两个组件相互连接起来。

我创建了一个简单的挂钩


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

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

  return {
    sharedXValue,
  };
};

export default useAppState;

使用复活的 2

中的 useSharedValue 保存共享值

child 组件在 gestureHandler 中使用该值


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

Parent只是消耗了挂钩值

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

我创建了一个 workable Snack,其中包含 2 个组件 - 一个带有蓝色方框的 Child 和一个带有红色方框的 Parent