React中Async/Await异步请求偶现Promise未正常解析问题求助
React异步请求偶现Promise未解析、data为null/undefined的问题解决
问题根源分析
useApi中的request函数没有返回请求结果,导致.then()回调无法获取响应数据(这就是你看到参数a为undefined的原因)- 依赖
useApi内部的data状态更新组件的shortenedUrl,但React状态更新是异步的,await request完成后,组件还没来得及重新渲染,此时getShortUrl.data可能还是旧值(null/undefined),从而导致偶现异常
修复步骤
1. 修改useApi Hook,让request返回结果并抛出错误
修改useApi的request函数,使其返回请求成功的数据,并在失败时抛出错误,这样调用方可以直接获取结果或捕获异常:
export const useApi = (apiFunc) => { const [data, setData] = useState(null); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const request = async (...args) => { setLoading(true); try { const result = await apiFunc(...args); setData(result.data); // 返回请求成功的数据 return result.data; } catch (err) { const errorMsg = err.message || "Unexpected Error!"; setError(errorMsg); // 抛出错误,让调用方可以捕获处理 throw new Error(errorMsg); } finally { setLoading(false); } }; return { data, error, loading, request }; };
2. 重构组件中的异步函数,直接使用返回结果更新状态
去掉await和.then()混合的写法,改用纯async/await,并直接用request返回的数据更新shortenedUrl,避免依赖异步更新的状态:
const getShortenedUrl = async () => { if (!url) { console.log("错误:URL不能为空"); return; } try { // 直接获取request返回的响应数据 const responseData = await getShortUrl.request(url); setShortenedUrl(responseData?.value); } catch (err) { console.error("URL缩短失败:", err.message); } };
3. 可选优化:避免重复请求与错误展示
- 给按钮添加禁用状态,防止加载中重复点击:
<button className="index__shortener__button" onClick={getShortenedUrl} disabled={getShortUrl.loading || !url} > {getShortUrl.loading ? "处理中..." : ( <> <BiCut size="2em" /> <span className="index__shortener__text"> Shorten URL</span> </> )} </button>
- 展示错误信息:
{getShortUrl.error && <p style={{color: "red"}}>{getShortUrl.error}</p>}
为什么之前的方案无效?
- 原
request函数没有返回值,所以.then()的回调参数必然是undefined - React的
setState是异步操作,即使request里调用了setData,await request完成后,getShortUrl.data并不会立刻更新,此时读取的还是组件当前渲染周期的旧值,这就是偶现null/undefined的核心原因
内容的提问来源于stack exchange,提问作者Radek L
相关产品推荐
相关产品推荐

