使用react-native-reanimated库报错:仅UI运行时可直接读取_value
解决"Reading from _value directly is only possible on the UI runtime"报错
错误原因
- 普通View不支持直接使用sharedValue:你直接把
useSharedValue创建的padding1/padding2传给原生View的style属性,但Reanimated的sharedValue只能在UI线程中读取,原生组件的style逻辑运行在JS线程,两者不匹配导致报错。 - 用setTimeout操作动画的问题:
setTimeout属于JS线程API,直接在其中修改sharedValue并调用withSpring(UI线程动画函数),会引发线程上下文不兼容的问题。
修复步骤
- 用Reanimated提供的
Animated.View替代原生View,这类组件专门适配UI线程的动画样式。 - 用Reanimated原生的
withDelay替代setTimeout,确保延迟逻辑在UI线程执行。 - 调整
withSpring的用法:直接传入目标值即可,无需基于当前sharedValue计算(动画函数内部会自动处理过渡过程)。
修复后的完整代码
import { View, Text, Image } from 'react-native' import React, { useEffect } from 'react' import { StatusBar } from 'expo-status-bar' import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen'; import { useSharedValue, withSpring, withDelay, runOnUI, Animated } from 'react-native-reanimated'; export default function Screen() { const padding1 = useSharedValue(0); const padding2 = useSharedValue(0); useEffect(() => { // 用runOnUI确保所有动画逻辑在UI线程执行 runOnUI(() => { padding1.value = withDelay(100, withSpring(hp(5))); padding2.value = withDelay(300, withSpring(hp(5.5))); })(); }, []); return ( <Animated.View className="bg-white/20 rounded-full" style={{ padding: padding2 }}> <Animated.View className="bg-white/20 rounded-full" style={{ padding: padding1 }}> <Image source={require('../../assets/welcome.png')} style={{ width: hp(20), height: hp(20) }} /> </Animated.View> </Animated.View> ) }
额外说明
- Animated组件:Reanimated的
Animated.*系列组件内置了UI线程适配逻辑,能正确识别并解析sharedValue类型的样式属性。 - runOnUI:由于
useEffect运行在JS线程,用这个API可以把动画相关的代码切换到UI线程执行,避免跨线程操作sharedValue的风险。
内容的提问来源于stack exchange,提问作者Santa
相关产品推荐
相关产品推荐

