React Native随机名言应用改色报错与下滑过渡动画实现问题
报错问题修复
错误原因
- React Native 无DOM环境,不能用Web端直接操作
ref.current.style的方式修改组件样式,该写法在RN中本身不兼容 - 你初始设置
quotes为空数组,首次useEffect触发时要么quoteRef.current未完成挂载为undefined,要么组件还未渲染,直接访问style属性自然触发报错 - 原代码中使用了
Platform但未导入,也会触发潜在报错
修复方案
新增颜色状态绑定样式,放弃ref直接操作样式的写法,拉取名言时同步生成随机颜色即可。
下滑动画实现
使用RN自带的Animated动画库即可实现,每次名言更新时控制文本Y轴偏移从上方负值平滑过渡到0,同步搭配透明度变化效果更自然。
修改后完整代码
import { StatusBar } from 'expo-status-bar'; import React from 'react'; // 新增导入Animated、Platform import { StyleSheet, Text, View, Button, SafeAreaView, ScrollView, Animated, Platform } from 'react-native'; import { useState, useEffect, useRef } from 'react'; export default function App() { // 初始quotes改为null,避免首次渲染空值报错 const [quotes, setQuotes] = useState(null); // 新增颜色状态 const [quoteColor, setQuoteColor] = useState('#fff'); // 动画值ref,控制下滑偏移和透明度 const slideAnim = useRef(new Animated.Value(0)).current; let colors = ["#ffff00", "#90ee90","#ffa500", "#ff68ff", "#a9a9e7"] const getQuotes = () => fetch('https://quotable.io/quotes?page=1') .then(response => response.json()) .then(data => { let randomQuote = Math.floor(Math.random() * data.results.length); setQuotes(data.results[randomQuote]); // 拉取到新名言时同步生成随机颜色 setQuoteColor(colors[Math.floor(Math.random() * colors.length)]); }); useEffect(() => { getQuotes() }, []) // 监听quotes变化,触发下滑动画 useEffect(() => { if (!quotes) return; // 先重置动画值到上方-30位置,透明度为0 slideAnim.setValue(-30); // 开启动画,150ms过渡到原位,透明度变为1 Animated.timing(slideAnim, { toValue: 0, duration: 150, useNativeDriver: true }).start(); }, [quotes, slideAnim]) return ( <SafeAreaView style={styles.container}> <ScrollView contentContainerStyle={{alignItems: 'center', justifyContent: 'center', flex: 1}}> {/* 替换为Animated.Text,绑定动画样式和颜色 */} {quotes && <Animated.Text style={{ color: quoteColor, fontSize: 18, transform: [{ translateY: slideAnim }], opacity: slideAnim.interpolate({ inputRange: [-30, 0], outputRange: [0, 1] }) }} >{quotes.content}</Animated.Text>} <Button onPress={getQuotes} title="Refresh" color="#841584" accessibilityLabel="Refresh" style={{marginTop: 20}} /> <StatusBar style="auto" /> </ScrollView> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'blue', paddingHorizontal: 10, paddingTop: Platform.OS === 'android' ? 35 : 0, }, });
内容的提问来源于stack exchange,提问作者Ayse8888
相关产品推荐
相关产品推荐

