React Native Reanimated:如何在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比较,改用以下方式:
- 用
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>; }); - 避免误用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
相关产品推荐
相关产品推荐

