React useEffect中获取Fetch返回值且不打乱事件序列的问题解决——处理shared变量未定义与加载动画逻辑冲突
问题分析与解决方案
首先,你的核心问题是混合使用了async/await和.then()链式调用,导致await没有覆盖完整的异步流程,所以shared还没被赋值就执行了后续的Firestore操作,自然会是undefined。另外,你的加载状态逻辑也存在问题——现在的代码里setLoading(true)和setLoading(false)几乎同步执行,加载动画根本来不及正常展示。
问题拆解
你用await fetch(...)等待了请求响应,但res.json().then(...)是另一个独立的异步操作,外层的await并没有等待这个内部Promise完成。所以当代码走到const docRef = doc(db, 'data-shared', shared);时,shared还是初始的空字符串,后续操作自然会因为参数错误出问题。
同时,你现在的加载状态设置逻辑完全没考虑异步操作的耗时,请求还在处理中就直接关闭了加载动画,这会导致加载动画一闪而过甚至完全不显示,违背了原本的设计意图。
正确的实现方式
我们可以统一使用async/await语法,让所有异步操作都按顺序等待完成,同时把加载状态的控制放在正确的时机:
useEffect(() => { const getData = async () => { // 先开启加载动画,确保用户能看到加载状态 setLoading(true); dispatch(SetBackDrop(true)); try { // 等待fetch请求完成,拿到响应 const res = await fetch('/encrypt', { headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, method: 'POST', body: JSON.stringify({ clientId: params[1] }), }); // 等待响应解析为JSON格式 const data = await res.json(); // 提取需要的shared值 const shared = data.data.split('_Shared_')[1]; // 等待Firestore文档获取完成 const docRef = doc(db, 'data-shared', shared); const docSnap = await getDoc(docRef); const firestoreData = docSnap.data(); // 更新页面数据 setLoaded(firestoreData?.img); } catch (err) { // 统一捕获所有异步操作的错误,给出提示 dispatch(SetSnackBarMsg({ bool: true, msg: 'Cannot get data.' })); } finally { // 不管请求成功还是失败,最后都关闭加载动画 dispatch(SetBackDrop(false)); setLoading(false); } }; getData(); }, []);
关键改进点
- 统一async/await语法:去掉所有
.then()嵌套,用await等待每个异步操作,确保代码严格按顺序执行,shared只有在赋值完成后才会被传入Firestore操作。 - 正确控制加载状态:在所有异步操作开始前开启加载动画,在所有操作完成(成功或失败)后再关闭,保证加载动画能持续展示到数据准备完毕。
- 集中错误处理:用try/catch包裹所有异步逻辑,统一处理fetch请求、JSON解析、Firestore操作中可能出现的错误,避免遗漏异常场景。
这样修改后,shared就不会再出现undefined的情况,同时加载动画也能正常工作,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Richardson
相关产品推荐
相关产品推荐

