如何基于Reanimated库的sharedValue触发useEffect及最佳实践
你当前的写法存在问题:直接将sharedValue.value作为useEffect的依赖是不可靠的。因为sharedValue是Reanimated针对UI线程优化的特殊对象,它的value属性在JS线程的读取属于跨线程同步操作,React的依赖检测机制无法正确捕获其变化,所以useEffect大概率不会在sharedValue更新时触发。
以下是几种可靠的实现方式:
1. 使用useAnimatedReaction(推荐)
这是Reanimated v2+专门提供的用于监听sharedValue变化的Hook,适配跨线程环境:
import { useSharedValue, useAnimatedReaction, runOnJS } from 'react-native-reanimated'; const sharedValue = useSharedValue(0); // 监听sharedValue变化 useAnimatedReaction( // 第一个函数:返回需要监听的值 () => sharedValue.value, // 第二个函数:值变化时的回调(运行在UI线程) (newValue, oldValue) => { // 若要执行JS线程的逻辑,必须用runOnJS包裹 runOnJS(handleValueChange)(newValue, oldValue); }, [] // 依赖数组,若有其他需要监听的变量可添加 ); // 运行在JS线程的逻辑,可处理同步/异步操作 const handleValueChange = (newVal, oldVal) => { console.log('sharedValue更新:', newVal, oldVal); // 这里可以执行异步操作,比如网络请求 // fetch('/api/update', { method: 'POST', body: JSON.stringify({ value: newVal }) }); // 也可以更新React状态 // setSomeState(newVal); };
说明
useAnimatedReaction的回调默认运行在UI线程,因此执行JS线程的代码必须用runOnJS包裹,避免线程冲突。- 该Hook能精准捕获sharedValue的变化,无论值是在UI线程还是JS线程被修改。
2. 结合useDerivedValue与runOnJS
如果需要基于sharedValue派生新值的同时触发逻辑,可以用useDerivedValue:
import { useSharedValue, useDerivedValue, runOnJS } from 'react-native-reanimated'; const sharedValue = useSharedValue(0); useDerivedValue(() => { const currentValue = sharedValue.value; runOnJS(handleValueChange)(currentValue); return currentValue; });
这种方式更适合需要派生值的场景,单纯监听变化优先用useAnimatedReaction。
关键注意事项
- 永远不要用
useEffect监听sharedValue.value,React无法感知跨线程的值变化。 - 所有涉及JS线程的操作(比如更新React状态、调用异步API)必须放在
runOnJS包裹的函数中执行,避免跨线程错误。
内容的提问来源于stack exchange,提问作者dan_boy
相关产品推荐
相关产品推荐

