React Native点击按钮无重渲染切换图片,解决白屏延迟问题
解决图片切换白屏+无延迟切换问题
问题根源
白屏是因为图片未预加载,每次点击切换才开始加载新图,导致短暂空白;另外原代码用useEffect监听count更新状态的方式,会触发多次组件重渲染,虽不是白屏主因,但可优化。
解决步骤
1. 预加载所有启动页图片
组件挂载时就把三张图加载到缓存,切换时直接调用缓存资源:
import { Image } from 'react-native'; // 批量预加载图片 const preloadImages = async () => { const imageList = [images.start_1, images.start_2, images.start_3]; await Promise.all(imageList.map(img => Image.prefetch(img.uri))); };
在组件初始化时执行预加载:
useEffect(() => { preloadImages(); }, []);
2. 优化状态逻辑,减少重渲染
把图片和文本整合成数组,直接通过count索引获取当前页数据,避免多次setState触发的组件更新:
const [count, setCount] = useState(1); // 启动页数据集合 const slides = [ { image: images.start_1, text: "Discover the\nmost beautiful\nroads in the\nworld" }, { image: images.start_2, text: "Make a road trip\nthrough fantastic\nlandscapes." }, { image: images.start_3, text: "Share your\nunique experiences\nwith others." } ]; // 直接获取当前页数据 const currentSlide = slides[count - 1];
3. 修改渲染代码,移除多余useEffect
将原代码中image和text替换为currentSlide的属性,跳转逻辑直接写在点击事件里,删掉原有的useEffect监听:
return ( <ImageBackground resizeMode='stretch' source={currentSlide.image} defaultSource={images.start_1} style={{ flex: 1 }}> <Text style={{ fontSize: 30, color: 'white', position: 'absolute', bottom: 120, left: 20 }}>{currentSlide.text}</Text> <TouchableOpacity activeOpacity={0.8} onPress={() => { count === 3 ? navigation.replace('home') : setCount(count + 1); }} style={{ position: 'absolute', bottom: 55, right: 20 }}> <ImageBackground resizeMode='cover' source={images.button} style={{ paddingVertical: 5, paddingHorizontal: 40, justifyContent: 'center', alignItems: 'center' }} imageStyle={{ borderRadius: 20 }}> <Text style={{ fontSize: 20, color: 'white' }}>Start</Text> </ImageBackground> </TouchableOpacity> </ImageBackground> );
4. 本地图片注意事项
如果是本地图片,确保images对象路径正确,示例:
const images = { start_1: require('./assets/start1.png'), start_2: require('./assets/start2.png'), start_3: require('./assets/start3.png'), button: require('./assets/button.png') };
预加载本地图片时,需通过require('./assets/start2.png').uri获取图片路径。
完整优化代码
import { useState, useEffect } from 'react'; import { Text, TouchableOpacity, ImageBackground, Image } from 'react-native'; export const Start = ({ navigation }) => { const [count, setCount] = useState(1); const slides = [ { image: images.start_1, text: "Discover the\nmost beautiful\nroads in the\nworld" }, { image: images.start_2, text: "Make a road trip\nthrough fantastic\nlandscapes." }, { image: images.start_3, text: "Share your\nunique experiences\nwith others." } ]; useEffect(() => { const preload = async () => { await Promise.all(slides.map(slide => Image.prefetch(slide.image.uri))); }; preload(); }, []); const currentSlide = slides[count - 1]; return ( <ImageBackground resizeMode='stretch' source={currentSlide.image} defaultSource={images.start_1} style={{ flex: 1 }}> <Text style={{ fontSize: 30, color: 'white', position: 'absolute', bottom: 120, left: 20 }}>{currentSlide.text}</Text> <TouchableOpacity activeOpacity={0.8} onPress={() => { count === 3 ? navigation.replace('home') : setCount(count + 1); }} style={{ position: 'absolute', bottom: 55, right: 20 }}> <ImageBackground resizeMode='cover' source={images.button} style={{ paddingVertical: 5, paddingHorizontal: 40, justifyContent: 'center', alignItems: 'center' }} imageStyle={{ borderRadius: 20 }}> <Text style={{ fontSize: 20, color: 'white' }}>Start</Text> </ImageBackground> </TouchableOpacity> </ImageBackground> ); };
内容的提问来源于stack exchange,提问作者mayra
相关产品推荐
相关产品推荐

