React Native Gesture Handler跨线程报错:手势回调中如何更新状态?
在React Native Gesture Handler中正确更新组件状态
当在React Native Gesture Handler的Pan手势.onEnd()回调中直接调用React状态更新方法时,会抛出错误:Tried to synchronously call function from a different thread,原代码如下:
const [localShowRecents, setLocalShowRecents] = useState(false) const translateY = useSharedValue(0); const gesture = Gesture.Pan() .onStart(() => { context.value = { y: translateY.value } }) .onUpdate((event) => { //console.log(event.translationY); translateY.value = event.translationY + context.value.y; translateY.value = Math.max(translateY.value, MAX_TRANSLATE_Y) }) .onEnd(() => { if (translateY.value > -SCREEN_HEIGHT / 32){ setLocalShowRecents(true); //change state } })
解决方法
Gesture Handler的手势回调(比如onEnd)运行在非主线程,而React的状态更新必须在主线程执行。只需使用Reanimated提供的runOnJS函数,将状态更新方法包裹后再调用,就能确保代码在主线程执行。
修改后的代码:
import { runOnJS } from 'react-native-reanimated'; // 记得导入runOnJS const [localShowRecents, setLocalShowRecents] = useState(false) const translateY = useSharedValue(0); const gesture = Gesture.Pan() .onStart(() => { context.value = { y: translateY.value } }) .onUpdate((event) => { translateY.value = event.translationY + context.value.y; translateY.value = Math.max(translateY.value, MAX_TRANSLATE_Y) }) .onEnd(() => { if (translateY.value > -SCREEN_HEIGHT / 32){ runOnJS(setLocalShowRecents)(true); // 用runOnJS包裹状态更新方法 } })
补充说明
runOnJS的作用是将传入的函数调度到JavaScript主线程执行,彻底避免跨线程调用的问题。- 请确保已经正确安装并配置了
react-native-reanimated和react-native-gesture-handler,否则可能出现其他异常。
内容的提问来源于stack exchange,提问作者Ethan Stacey
相关产品推荐
相关产品推荐

