如何在所有子组件useEffect及fetch请求完成前展示加载屏?
多子组件全量加载完成前统一显示加载屏的实现方案
方案1:父组件托管加载状态(适用子组件层级浅的场景)
核心逻辑是把加载完成状态的控制权从单个子组件上移到首页父组件,父组件统一统计所有子组件的加载完成情况,全部完成后再关闭加载屏。
实现步骤
- 父组件定义加载完成状态集合,存储每个子组件的完成状态,同时计算全局完成标志:
import { useState } from 'react' import Comp1 from './Comp1' // 其余子组件引入省略 export default function Home() { // 初始化5个子组件的完成状态,默认都是未完成 const [compFinishState, setCompFinishState] = useState({ comp1: false, comp2: false, comp3: false, comp4: false, comp5: false }) // 判断是否所有子组件都加载完成 const isAllLoaded = Object.values(compFinishState).every(item => item === true) // 生成对应子组件的完成回调 const handleFinish = (compKey) => { setCompFinishState(prev => ({ ...prev, [compKey]: true })) } return ( <div> {/* 未全部加载完成时显示全局加载屏 */} {!isAllLoaded && <div className="global-loading">加载中...</div>} {/* 加载完成后才渲染内容,或者也可以一直渲染子组件,加载屏盖在顶层 */} {isAllLoaded && ( <> <Comp1 onFinish={() => handleFinish('comp1')} /> <Comp2 onFinish={() => handleFinish('comp2')} /> <Comp3 onFinish={() => handleFinish('comp3')} /> <Comp4 onFinish={() => handleFinish('comp4')} /> <Comp5 onFinish={() => handleFinish('comp5')} /> </> )} </div> ) }
- 每个子组件内部统计自身所有useEffect逻辑、API请求的完成状态,全部处理完成后调用父组件传入的
onFinish回调:
// 子组件示例 import { useEffect } from 'react' export default function Comp1({ onFinish }) { useEffect(() => { // 合并当前子组件所有的API请求 const fetchAllData = async () => { const req1 = fetch('/api/xxx1') const req2 = fetch('/api/xxx2') const req3 = fetch('/api/xxx3') try { // 等待所有请求完成,无论成功失败都标记完成 await Promise.allSettled([req1, req2, req3]) // 这里可以处理请求成功的逻辑 } catch (err) { // 处理错误提示 } finally { // 全部处理完成后通知父组件 onFinish?.() } } fetchAllData() }, [onFinish]) return <div>子组件1内容</div> }
方案2:Context全局管理(适用子组件层级深、透传props不便的场景)
如果子组件嵌套层级深,透传onFinish回调麻烦,可以通过React Context做全局状态管理:
- 顶层创建
LoadStatusContext,提供标记子组件完成的方法和全局完成状态 - 每个子组件通过
useContext拿到标记完成的方法,自身全部加载完成后调用 - 父组件消费Context中的全局完成状态,控制加载屏的显示隐藏
注意事项
- 必须处理请求异常场景,不要因为单个接口报错导致加载屏一直显示,建议用
Promise.allSettled替代Promise.all包裹同批次请求,无论成功失败都标记为完成,错误由对应子组件单独提示 - 如果子组件有依赖项更新导致的重复请求逻辑,需要同步更新完成状态,触发全局加载屏的重新显示
- 存在条件渲染的子组件时,需要动态调整父组件统计的子组件范围,避免多统计未渲染的组件导致加载屏无法关闭
内容的提问来源于stack exchange,提问作者axfg
相关产品推荐
相关产品推荐

