You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Reanimated 2动画结束触发导航崩溃如何解决

崩溃根因

react-native-reanimated 搭配 react-native-gesture-handler 使用时,Gesture.Pan() 下的 onBegin/onUpdate/onEnd/onFinalize 回调默认运行在UI工作线程(Worklet),和React Native常规JS逻辑线程是隔离的。你左右滑动逻辑只修改Reanimated的sharedValue值,这类操作原生支持跨线程访问所以不会崩溃;但你在回调里直接调用React Navigation的navigate方法属于JS线程的API,直接跨线程调用就会触发应用崩溃。你之前尝试的清缓存、重装App都无法解决问题,因为这是API使用规则不符导致的逻辑错误,和环境无关。

修复方案
  • 从react-native-reanimated导入runOnJS工具方法,所有需要在Worklet线程调用JS侧逻辑(导航、console打印、状态更新等)的场景,都要用runOnJS包裹后再执行
  • 修正你当前写反的上下滑判断逻辑:y.value为正数代表手指向下滑动,为负数代表手指向上滑动,你当前代码判断y.value > windowHeight/4的分支注释写的是swiped up,逻辑完全颠倒
  • 移除Worklet回调里直接写的console.log,避免不必要的跨线程通信开销
核心修改代码

首先修改导入部分:

// 原来的Animated导入追加runOnJS
import Animated, { useSharedValue, useAnimatedStyle, withSpring, runOnJS } from "react-native-reanimated";

然后修改Pan手势的onEnd回调部分:

.onEnd((e) => {
  const verticalSwipe = Math.abs(y.value) - Math.abs(x.value);
  // 原代码声明的horizontalSwipe变量未被使用,可以直接删除

  if (verticalSwipe >= 0) {
    // 向下滑动超过屏幕1/4高度触发导航,可根据需求调整阈值
    if (y.value > windowHeight / 4) { 
      // 用runOnJS包裹JS侧的导航方法再调用
      runOnJS(navigateToHome)();
    } else {
      x.value = withSpring(startPosition);
      y.value = withSpring(startPosition);
    }
  } else {
    if (x.value > windowWidth / 4) {
      x.value = withSpring(windowWidth * 2);
      y.value = withSpring(startPosition)
    } else if (x.value < -windowWidth / 4) {
      x.value = withSpring(-windowWidth * 2);
      y.value = withSpring(startPosition);
    } else {
      x.value = withSpring(startPosition);
      y.value = withSpring(startPosition);
    }
  }
})
额外优化建议
  • 你代码里声明了offset、start两个sharedValue但是完全没用到,可以删掉减少不必要的性能开销
  • useWindowDimensions不需要每次render重复调用三次,只需要调用一次解构出width和height即可
  • 如果后续要做下滑打开详情的卡片跟手动画,可以在onUpdate里判断垂直滑动占优时,给卡片加缩放、圆角变化的过渡效果,体验会更接近原生Tinder的交互

内容的提问来源于stack exchange,提问作者Damon Guzman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:48:18