React Native首次点击动画不触发及ref绑定动画TS类型问题
问题原因
1. 首次点击动画不触发
核心是动画目标值逻辑写错:
- 初始
show状态为false,对应动画值应为0,组件首次渲染时Animated.Value初始值已经是0 - 第一次点击触发时,闭包捕获的
show还是初始值false,原代码里toValue: show ? 200 : 0计算结果为0,和当前动画值完全一致,没有状态差,动画自然不会执行 - 执行完
setShow(!show)后show变成true,第二次点击时计算出的toValue才是200,和当前值0有差值,动画才会启动
另外原代码里interpolate输入区间是[0,100],但动画目标值最大到200,超过100的区间颜色不会继续变化,也不符合预期。
2. 动画值的TS类型定义错误
用any规避类型有两个原因:一是直接把useRef返回对象的current属性提前解构赋值给普通变量,二是没有给useRef传入对应泛型声明存储值的类型,TS无法自动推导值的类型。实际上react-native已经内置了Animated.Value的类型声明,完全不需要用any。
修复方法
- 修正动画目标值计算逻辑:点击切换时,目标值要对应切换后的
show状态,而不是切换前的旧状态 - 修正
interpolate输入区间,覆盖完整的动画值范围0-200 - 修正动画值ref的写法:不要提前解构
.current赋值,给useRef传入泛型声明存储的值类型为Animated.Value,使用时再取.current属性,TS可以自动推导正确类型
修复后完整代码
import React from 'react'; import { View, Animated } from 'react-native'; const Test = () => { // 正确的TS类型定义,不需要any const messRef = React.useRef<Animated.Value>(new Animated.Value(0)); const [show, setShow] = React.useState<boolean>(false); return ( <View> <Animated.Text onPress={() => { const nextShow = !show; // 目标值对应切换后的状态 Animated.timing(messRef.current, { toValue: nextShow ? 200 : 0, duration: 1000, useNativeDriver: false, }).start(); setShow(nextShow); }} style={{ // 输入区间覆盖0-200的完整动画范围 color: messRef.current.interpolate({ inputRange: [0, 200], outputRange: ["orange", "blue"], }), }} > Everything you do in life stems from either fear or love </Animated.Text> </View> ); }; export default Test;
补充说明:如果开启了React严格模式,不要在组件渲染阶段提前解构ref的current属性存为外部常量,否则严格模式双执行时可能拿到非预期的引用,直接通过
ref.current访问属性是最稳妥的写法。
内容的提问来源于stack exchange,提问作者user19539777
相关产品推荐
相关产品推荐

