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

React Native Reanimated:如何在memo回调中比较SharedValue属性?

在memo回调中比较SharedValue属性的正确方式

核心结论

不能在memo的arePropsEqual回调中直接访问SharedValue的.value属性,也不能用_.isEqual比较整个SharedValue对象——前者会触发UI线程访问限制错误,后者会因遍历内部属性触发同样问题。

选项分析

对四个选项逐一拆解:

  • 选项1:_.isEqual(prevProps.animatedProgress, nextProps.animatedProgress)
    错误。SharedValue内部包含仅能在UI线程访问的属性(如_value),_.isEqual会遍历这些属性,直接触发Error: [Reanimated] Reading from _value directly is only possible on the UI runtime错误。
  • 选项2:prevProps.animatedProgress === nextProps.animatedProgress
    仅在SharedValue实例本身替换时返回false。如果只是SharedValue的value变化、实例引用不变,该比较会错误地认为props未变化,导致组件无法触发重渲染,不符合需求。
  • 选项3/4:直接比较.value
    错误。arePropsEqual运行在JS线程,直接访问SharedValue的.value会触发上述UI线程访问限制错误;且JS线程获取的.value是异步同步的,回调执行时可能还未拿到最新值,出现你遇到的“打印旧值”问题。

正确处理方案

如果需要基于SharedValue的value变化触发组件重渲染,不要依赖memo的props比较,改用以下方式:

  1. 用useAnimatedReaction监听value变化并同步状态
    在UI线程监听SharedValue的value更新,同步到React状态触发组件重渲染:
    import { useAnimatedReaction } from 'react-native-reanimated';
    import { useState, memo } from 'react';
    
    const YourComponent = memo(({ animatedProgress }) => {
      const [progressValue, setProgressValue] = useState(animatedProgress.value);
    
      useAnimatedReaction(
        () => animatedProgress.value,
        (newValue) => {
          setProgressValue(newValue);
        },
        [animatedProgress]
      );
    
      // 基于同步后的progressValue渲染UI
      return <Text>当前进度:{progressValue}</Text>;
    });
    
  2. 避免误用memo
    如果组件的渲染依赖SharedValue的value变化,且SharedValue实例本身不会替换,memo的默认浅比较会阻止重渲染,此时可以直接去掉memo,或结合上述状态同步方案使用。

你遇到的问题解释

  • UI线程访问错误:_.isEqual遍历SharedValue对象时,尝试读取了仅允许在UI线程访问的内部属性(如_value),而arePropsEqual运行在JS线程,因此触发错误。
  • 打印旧值:SharedValue的value更新先在UI线程生效,同步到JS线程是异步操作,当arePropsEqual执行时,JS线程还未拿到最新值,所以显示的是上一次的结果。

内容的提问来源于stack exchange,提问作者Victorio Jesús Molina Bermejo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:59:59