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

ReanimatedSwipeable组件持续触发‘读取value’警告的排查求助

解决ReanimatedSwipeable渲染时读取Shared Value的警告

问题核心

你收到的警告源于两个关键问题:

  • 违反React Hooks规则:renderLeftActions和renderRightActions是普通回调函数,你在里面直接调用了useDerivedValue、useAnimatedStyle这类React Hooks——Hooks只能在组件或自定义Hooks的顶层调用,不能嵌套在普通函数中。
  • 渲染阶段访问Shared Value:由于Hooks被错误地放在渲染时执行的回调里,导致Reanimated检测到组件渲染流程中读取了dragX.value这类Shared Value的属性,触发警告。

修复步骤

把左右滑动操作的渲染逻辑重构为独立组件,让Hooks在组件顶层正常执行:

1. 重构LeftAction组件

const LeftAction = ({ dragX, index, item, setActivePlan }) => {
  // Hooks移至组件顶层
  const translateX = useDerivedValue(() => dragX.value - 60, [dragX]);

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

  return (
    <TouchableOpacity
      onPress={async () => await setActivePlan(index, item)}
      style={styles.defaultButton}>
      <Animated.Text style={[styles.defaultButtonText, styleAnimation]}>Set</Animated.Text>
    </TouchableOpacity>
  );
};

2. 重构RightAction组件

const RightAction = ({ dragX, item, deleteWorkoutPlan }) => {
  const animatedStyle = useAnimatedStyle(() => {
    const translateX = interpolate(
      dragX.value,
      [-60, 0],
      [0, 80],
      Extrapolation.CLAMP
    );

    return {
      transform: [{ translateX }],
    };
  });

  return (
    <TouchableOpacity
      onPress={() => deleteWorkoutPlan(item)}
      style={styles.deleteButton}>
      <DeleteIcon name="trash-outline" color={COLORS.white} size={24} animatedProps={animatedStyle} />
    </TouchableOpacity>
  );
};

3. 修改PlanItem组件调用逻辑

在PlanItem中直接使用重构后的组件,替代原回调函数:

const PlanItem = ({ item, index, setActivePlan, deleteWorkoutPlan, swipeableRefs }) => {
  const translateX = useSharedValue(0);
  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: withTiming(translateX.value, { duration: 300 }) }],
      opacity: interpolate(translateX.value, [-500, 0], [0, 1], Extrapolation.CLAMP),
    };
  });

  return (
    <Animated.View style={animatedStyle}>
      <ReanimatedSwipeable
        key={item.id} // 用item.id替代index作为key,避免数据更新时组件复用异常
        overshootRight={false}
        overshootLeft={false}
        friction={2}
        ref={(ref) => (swipeableRefs.current[index] = ref)}
        renderRightActions={(dragX) => <RightAction dragX={dragX} item={item} deleteWorkoutPlan={deleteWorkoutPlan} />}
        renderLeftActions={(dragX) => <LeftAction dragX={dragX} index={index} item={item} setActivePlan={setActivePlan} />}
      >
        <Pressable onPress={() => handlePlanPressed(item)}>
          <View style={styles.card}>
            <Text style={styles.planTitle}>{item.name}</Text>
          </View>
        </Pressable>
      </ReanimatedSwipeable>
    </Animated.View>
  );
};

额外优化

  • 确保swipeableRefs、setActivePlan、deleteWorkoutPlan等依赖被正确传递到PlanItem组件。
  • 用item.id作为组件key,比index更稳定,避免FlatList数据变动时的渲染异常。

完成重构后,Hooks会在组件顶层执行,不再在渲染阶段触发Shared Value的读取操作,警告即可消除。

内容的提问来源于stack exchange,提问作者Raul kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:50:13