React Suspense加载异常:骨架屏消失后短暂无内容显示
问题原因分析
你遇到的空白期问题根源很明确:React.lazy + Suspense 只负责处理组件代码的懒加载,不涵盖组件内部的数据请求阶段。
当Articles组件的代码包加载完成后,Suspense就会立刻收起fallback骨架屏,此时Articles组件已经挂载,但useEffect触发的异步请求还在后台跑——这时候因为articles状态还没数据,你又只在articles存在时渲染列表,自然就出现了空白,直到请求完成才显示内容。
两种解决方案
方案1:用React 18+的use钩子让Suspense覆盖数据加载阶段
use钩子可以直接在组件中消费Promise,并且会触发Suspense的fallback逻辑,直到Promise resolve。这样就能让骨架屏持续显示到数据加载完成:
// Articles.jsx import { use } from 'react'; // 封装数据请求 const fetchArticles = async () => { const res = await fetch('/api/articles'); if (!res.ok) throw new Error('请求失败'); return res.json(); }; export default function Articles() { // 直接用use消费请求Promise,未完成时Suspense会继续显示骨架屏 const articles = use(fetchArticles()); return ( <ul> {articles.map(article => ( <li key={article.id}>{article.title}</li> ))} </ul> ); }
方案2:组件内部维护加载状态,自己控制骨架屏显示
如果不想用use钩子,也可以在Articles组件里自己加加载状态,让骨架屏持续显示到数据就绪:
// Articles.jsx import { useState, useEffect } from 'react'; import ArticlesSkeletons from './ArticlesSkeletons'; export default function Articles() { const [articles, setArticles] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const getArticles = async () => { try { const res = await fetch('/api/articles'); const data = await res.json(); setArticles(data); } catch (err) { // 处理错误 console.error(err); } finally { setIsLoading(false); } }; getArticles(); }, []); // 数据加载完成前一直显示骨架屏 if (isLoading) { return <ArticlesSkeletons />; } return ( <ul> {articles.map(article => ( <li key={article.id}>{article.title}</li> ))} </ul> ); }
这种方式下,外层Suspense的骨架屏负责组件代码加载,组件内部的骨架屏负责数据加载,全程不会出现空白。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

