【问题标题】:How to use PanResponder in functional components?如何在功能组件中使用 PanResponder?
【发布时间】:2019-11-19 17:18:37
【问题描述】:

我找到的官方文档和所有教程都使用 PanResponder 作为 React 类的一部分,但是有没有办法可以将它与功能组件和钩子一起使用? 我尝试按如下方式进行操作,但似乎不起作用:-

const App = props => {
  const position = useRef(new Animated.ValueXY()).current;
  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onPanResponderMove: (evt, gestureState) => {
        position.setValue({x: gestureState.dx, y: gestureState.dy});
      },
      onPanResponderRelease: (evt, gestureState) => {},
    }),
  ).current;

...

<Animated.View
            {...panResponder.panHandlers}
            style={[
              {transform: position.getTranslateTransform()},
              styles.appStyles,
            ]}>
...
</Animated.View>

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    在这里找到解决方案:https://github.com/facebook/react-native/issues/25360#issuecomment-505241400

    useMemo 避免在每次重新渲染时重新创建 PanResponder

    那么你的代码应该是这样的

    const App = props => {
      const position = useRef(new Animated.ValueXY()).current;
      const panResponder = React.useMemo(() => PanResponder.create({
          onStartShouldSetPanResponder: (evt, gestureState) => true,
          onPanResponderMove: (evt, gestureState) => {
            position.setValue({x: gestureState.dx, y: gestureState.dy});
          },
          onPanResponderRelease: (evt, gestureState) => {},
        }), []);
    
    ...
    
    <Animated.View
                {...panResponder.panHandlers}
                style={[
                  {transform: position.getTranslateTransform()},
                  styles.appStyles,
                ]}>
    ...
    </Animated.View>
    

    【讨论】:

    • 这是错误的。使用备忘录,如果您再次创建 panResponder,您的 pan 处理程序将永远到达那里。然后他们将阻止 InteractionManager。
    • @DiogoAleixo 你有其他解决方案吗?
    【解决方案2】:

    官方文档建议使用useRef()

    https://reactnative.dev/docs/panresponder

    以下是从官方文档中复制的示例

    const ExampleComponent = () => {
      const panResponder = React.useRef(
        PanResponder.create({
          // Ask to be the responder:
          onStartShouldSetPanResponder: (evt, gestureState) => true,
          onStartShouldSetPanResponderCapture: (evt, gestureState) =>
            true,
          onMoveShouldSetPanResponder: (evt, gestureState) => true,
          onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
            true,
    
          onPanResponderGrant: (evt, gestureState) => {
            // The gesture has started. Show visual feedback so the user knows
            // what is happening!
            // gestureState.d{x,y} will be set to zero now
          },
          onPanResponderMove: (evt, gestureState) => {
            // The most recent move distance is gestureState.move{X,Y}
            // The accumulated gesture distance since becoming responder is
            // gestureState.d{x,y}
          },
          onPanResponderTerminationRequest: (evt, gestureState) =>
            true,
          onPanResponderRelease: (evt, gestureState) => {
            // The user has released all touches while this view is the
            // responder. This typically means a gesture has succeeded
          },
          onPanResponderTerminate: (evt, gestureState) => {
            // Another component has become the responder, so this gesture
            // should be cancelled
          },
          onShouldBlockNativeResponder: (evt, gestureState) => {
            // Returns whether this component should block native components from becoming the JS
            // responder. Returns true by default. Is currently only supported on android.
            return true;
          }
        })
      ).current;
    
      return <View {...panResponder.panHandlers} />;
    };
    

    【讨论】:

    • useRef 是正确的,这应该是公认的答案
    猜你喜欢
    • 2020-11-09
    • 1970-01-01
    • 2020-06-16
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2022-12-17
    相关资源
    最近更新 更多