React全局加载遮罩未正常工作的原因排查与解决请求
解决方案:全局加载状态异常问题
问题核心原因
你的代码中startLoading和stopLoading直接引用了当前渲染周期的loading状态快照,由于React的useState是异步更新,当多个请求并发触发状态更新时,会因为闭包陷阱导致状态更新丢失或不准确,最终出现数组为空但加载组件仍显示的情况。
修复方案
使用React的函数式状态更新替代直接依赖当前状态,确保每次状态更新都基于最新的状态值:
修改后的LoadingContext.jsx
'use strict'; import React, { createContext, useContext, useState, } from 'react'; const LoadingContext = createContext({ startLoading: (id) => {}, stopLoading: (id) => {}, isLoading: false, }); export const useLoading = () => useContext(LoadingContext); export const LoadingProvider = ({ children }) => { const [loading, setLoading] = useState([]); const startLoading = (id) => { // 函数式更新,基于最新状态添加ID,同时避免重复添加 setLoading(prevLoading => { if (!prevLoading.includes(id)) { return [...prevLoading, id]; } return prevLoading; }); }; const stopLoading = (id) => { // 函数式更新,基于最新状态过滤掉目标ID setLoading(prevLoading => prevLoading.filter(item => item !== id)); }; return ( <LoadingContext.Provider value={{ startLoading, stopLoading, isLoading: loading.length > 0, }}> {children} </LoadingContext.Provider> ); }
额外优化建议
- 请求ID唯一性:确保每个请求的ID唯一,比如在并发请求时,可以给ID添加时间戳或者随机后缀,避免不同请求使用相同ID导致的状态混乱。
- 异常兜底:你的代码已经用
finally包裹stopLoading,能确保无论请求成功或失败都会终止加载状态,这部分无需修改。
内容的提问来源于stack exchange,提问作者bohrsty
相关产品推荐
相关产品推荐

