React Native中PanGestureHandler报错:期望'onGestureHandlerEvent'为函数
解决React Native中PanGestureHandler报错:Expected
onGestureHandlerEvent listener to be a function 问题重现
我是React Native新手,按照官方文档编写PanGestureHandler相关代码:
import { GestureHandlerRootView,PanGestureHandler } from "react-native-gesture-handler"; import { useEffect } from "react"; import { Animated,Button,Dimensions,StyleSheet,ScrollView ,View,Text} from "react-native"; import { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring, withTiming } from "react-native-reanimated"; export default function App () { const progress= useSharedValue(2) const panHandler=useAnimatedGestureHandler({ onStart:(event,context)=>{}, onActive:(event,context)=>{}, onEnd:(event,context)=>{} }) const animatedStyle=useAnimatedStyle(()=>{ return{ borderRadius:progress.value*30 } }) return( <GestureHandlerRootView > <PanGestureHandler onGestureEvent={panHandler}> <Animated.View style={[styles.container,animatedStyle]}><Text>test</Text> </Animated.View> </PanGestureHandler> </GestureHandlerRootView> )}
运行后触发错误:
ERROR Error: Expected `onGestureHandlerEvent` listener to be a function, instead got a value of `object` type.
错误原因
你使用了react-native-gesture-handler原生的PanGestureHandler组件,但绑定了Reanimated的useAnimatedGestureHandler返回的处理函数——两者不兼容。useAnimatedGestureHandler返回的是Reanimated专用的手势处理器对象,而非普通函数,原生PanGestureHandler无法识别该对象,因此抛出错误。
修复方案
方案1:使用Reanimated包装的PanGestureHandler
直接从react-native-reanimated导入已兼容的PanGestureHandler:
import { GestureHandlerRootView } from "react-native-gesture-handler"; import { useEffect } from "react"; import { Animated, Button, Dimensions, StyleSheet, ScrollView, View, Text } from "react-native"; import { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring, withTiming, PanGestureHandler // 从reanimated导入 } from "react-native-reanimated"; export default function App () { const progress= useSharedValue(2) const panHandler=useAnimatedGestureHandler({ onStart:(event,context)=>{}, onActive:(event,context)=>{ // 示例:根据拖拽X轴距离更新borderRadius progress.value = event.translationX / 100 + 2; }, onEnd:(event,context)=>{} }) const animatedStyle=useAnimatedStyle(()=>{ return{ borderRadius:progress.value*30 } }) // 补充必要样式 const styles = StyleSheet.create({ container: { width: 200, height: 200, backgroundColor: '#4287f5', justifyContent: 'center', alignItems: 'center', } }); return( <GestureHandlerRootView style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <PanGestureHandler onGestureEvent={panHandler}> <Animated.View style={[styles.container,animatedStyle]}><Text style={{color: 'white'}}>test</Text> </Animated.View> </PanGestureHandler> </GestureHandlerRootView> )}
方案2:手动包装原生PanGestureHandler
若需继续使用react-native-gesture-handler的原生组件,用Animated.createAnimatedComponent包装后再使用:
import { GestureHandlerRootView, PanGestureHandler } from "react-native-gesture-handler"; import { useEffect } from "react"; import { Animated, Button, Dimensions, StyleSheet, ScrollView, View, Text } from "react-native"; import { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring, withTiming } from "react-native-reanimated"; // 手动包装原生组件 const AnimatedPanGestureHandler = Animated.createAnimatedComponent(PanGestureHandler); export default function App () { const progress= useSharedValue(2) const panHandler=useAnimatedGestureHandler({ onStart:(event,context)=>{}, onActive:(event,context)=>{ progress.value = event.translationX / 100 + 2; }, onEnd:(event,context)=>{} }) const animatedStyle=useAnimatedStyle(()=>{ return{ borderRadius:progress.value*30 } }) const styles = StyleSheet.create({ container: { width: 200, height: 200, backgroundColor: '#4287f5', justifyContent: 'center', alignItems: 'center', } }); return( <GestureHandlerRootView style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <AnimatedPanGestureHandler onGestureEvent={panHandler}> <Animated.View style={[styles.container,animatedStyle]}><Text style={{color: 'white'}}>test</Text> </Animated.View> </AnimatedPanGestureHandler> </GestureHandlerRootView> )}
额外说明
- 补充
styles样式可避免视图无法正常显示的问题 - 你可以在
onActive回调中根据手势事件参数(如event.translationX/event.translationY)更新共享值,实现自定义交互逻辑
内容的提问来源于stack exchange,提问作者aboarab
相关产品推荐
相关产品推荐

