React(TypeScript)函数式组件调用AWS API遇报错求助
React异步API对接与状态更新问题
问题背景
我是React新手,尤其不熟悉React与后端服务的对接。我有一个React函数式组件Game,用于维护当前局面的评估值,同时已创建AWS API返回(-10,10)范围内的随机评估数值。我在组件中编写了如下代码:
const [evaluation, setEvaluation] = React.useState<number>(0.0); // ... const getEvalAfterMove = async (board: string[], nextPlayer: string) => { async function fetchData() { const response = await fetch('my/api/link'); const data = await response.json(); setEvaluation(data); } fetchData(); };
Game组件内包含GameGrid组件,后者由Square组件构成,getEvalAfterMove会逐层传递给每个Square组件,绑定到其onClick事件。但点击Square时,浏览器报TypeError: Failed to Fetch,无法获取数值,不过直接访问API调用URL能正常返回随机值的JSON。
我想确认:
getEvalAfterMove因异步是否独立于React应用执行?- 如何通过API调用在每次点击Square后更新
evaluation状态? - 是否需要添加加载状态等待响应?
解答
1. 异步函数与React应用的关系
getEvalAfterMove并非完全独立于React执行:
- 函数本身在React组件上下文里定义,触发时机由React的事件系统(
Square的onClick)控制。 - 内部的
fetch异步请求会进入浏览器事件队列执行,脱离React的同步渲染流程,但调用setEvaluation更新状态时,该操作会触发React的状态更新机制,触发组件重新渲染。
2. 解决请求失败并正确更新状态
你遇到的Failed to Fetch几乎可以确定是CORS跨域问题:浏览器地址栏直接访问API不受同源策略限制,但React应用通过fetch发起的请求属于跨域请求,需要在AWS API Gateway中配置CORS规则,允许你的React应用域名的跨域访问(配置允许的Origin、请求方法、响应头)。
修复跨域后,优化代码以确保状态正确更新:
const getEvalAfterMove = async (board: string[], nextPlayer: string) => { try { const response = await fetch('my/api/link'); // 检查请求是否成功(处理4xx/5xx状态码) if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } const data = await response.json(); setEvaluation(data); } catch (error) { console.error('获取评估值失败:', error); // 可选:添加错误提示逻辑,比如设置错误状态告知用户 } };
优化点:
- 去掉嵌套的
fetchData函数,简化代码结构 - 用
try/catch捕获请求过程中的所有错误,便于排查 - 校验
response.ok避免解析错误的响应内容
跨域问题解决后,每次点击Square触发getEvalAfterMove,请求成功后setEvaluation会更新状态,React会自动重新渲染组件展示最新的评估值。
3. 是否需要添加加载状态
建议添加加载状态,提升用户体验:当API请求未完成时,用户能看到明确的加载提示,不会误以为点击无效。实现方式如下:
// 新增加载状态 const [isLoading, setIsLoading] = React.useState<boolean>(false); const getEvalAfterMove = async (board: string[], nextPlayer: string) => { setIsLoading(true); try { const response = await fetch('my/api/link'); if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } const data = await response.json(); setEvaluation(data); } catch (error) { console.error('获取评估值失败:', error); } finally { // 无论请求成功或失败,都结束加载状态 setIsLoading(false); } };
然后在组件中根据isLoading展示对应内容:
{isLoading ? ( <div>正在计算评估值...</div> ) : ( <div>当前局面评估值: {evaluation}</div> )}
内容的提问来源于stack exchange,提问作者crystaltine
相关产品推荐
相关产品推荐

