React isLoading状态异常:页面重载时骨架加载效果不生效
问题分析与解决方案
核心问题
页面刷新时骨架屏不显示的根本原因是:初始状态下voiceData.voices为空数组,导致骨架屏的map循环没有生成任何<Skeleton>组件——哪怕isLoading为true,也没有可渲染的内容,自然看不到加载效果。而Ctrl+S热重载时,React热模块替换可能保留了之前的voiceData状态,所以能正常渲染骨架。
解决方案
1. 初始化占位数据,确保骨架屏能渲染
修改voiceData的初始状态,给voices设置一个包含固定数量占位对象的数组,保证初始渲染时map能生成对应数量的骨架:
import { useState, useEffect } from 'react'; import axios from 'axios'; import Skeleton from './Skeleton'; import VoiceCard from './VoiceCard'; import { useNavigate } from 'react-router-dom'; const YourComponent = () => { // 初始化8个占位项,对应grid-cols-4的两行布局,可根据需求调整数量 const [voiceData, setVoiceData] = useState({ voices: Array(8).fill({ voice_id: Math.random() }) }); const [isLoading, setIsLoading] = useState(true); const navigate = useNavigate(); // ...其他逻辑 };
2. 优化骨架屏渲染逻辑(可选,更灵活)
直接渲染固定数量的骨架,不依赖voiceData,避免受接口数据影响:
{isLoading ? ( <div className="grid grid-cols-4 gap-3"> {/* 渲染8个骨架,数量可根据布局调整 */} {Array(8).fill(null).map((_, index) => ( <Skeleton key={index} className="w-[200px] h-[250px] rounded-md" /> ))} </div> ) : ( <div id="dash-card-container" className="grid grid-cols-4 gap-3"> {voiceData.voices.map((voice) => ( <VoiceCard onClick={() => { localStorage.setItem("voice", JSON.stringify(voice)); navigate("/create/editor"); }} key={voice.voice_id} img={voice.img} name={voice.name} category={voice.category} /> ))} </div> )}
3. 简化useEffect逻辑
初始isLoading已经设为true,不需要在请求时重复设置,同时保留finally块确保无论请求成功失败都能关闭加载状态:
useEffect(() => { const fetchVoices = async () => { try { const response = await axios.get("http://localhost:3000/voices"); setVoiceData(response.data); } catch (error) { console.error("Error fetching voices", error); } finally { setIsLoading(false); } }; fetchVoices(); }, []);
验证逻辑
修改后页面刷新时,初始渲染会直接生成对应数量的骨架组件,直到接口请求完成后切换为真实的VoiceCard组件,解决刷新时无加载效果的问题。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

