React中如何实现Fetch完成后渲染内容及规范错误处理
问题根因
你写的错误处理版本运行异常,核心是三个问题:
- Promise链逻辑断裂:
handleErrors校验通过后,你写了.then((response) => console.log("ok")),这一步没有把response对象返回给后续链式调用,后面执行response.json()时拿到的是console.log的返回值undefined,自然会报错;同时你把catch写在链中间,会提前吞掉前面抛出的错误,后续逻辑依然会执行。 - 缺少状态兜底:请求发出到响应返回有时间差,初始状态下
transaction是空数组,直接访问transaction.status会得到undefined,如果接口异常返回不符合预期的结构,还会直接导致页面渲染崩溃。 - 状态定义不合理:没有单独维护加载、请求错误的状态,既没法给用户展示提示,也没法控制内容只在请求完成后渲染。
正确实现代码
import React, { useState, useEffect } from "react"; function Transaction() { // 数据初始值用null,方便判断是否已拿到接口返回 const [transaction, setTransaction] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const token = "2c506c6b-d880-36bb-bdba-a035d1464b35"; const requestOptions = { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, }; function handleErrors(response) { if (!response.ok) { throw Error(response.statusText || `请求错误,状态码:${response.status}`); } return response; } useEffect(() => { // 请求发起前重置状态 setLoading(true); setError(null); fetch( "https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/transaction/5KISDW53", requestOptions ) .then(handleErrors) .then((response) => response.json()) .then((data) => setTransaction(data)) .catch((error) => setError(error.message)) .finally(() => setLoading(false)); }, []); // 按加载、错误、成功的顺序判断渲染内容,保证只有请求完成才展示业务数据 if (loading) return <div>正在加载交易信息...</div>; if (error) return <div style={{ color: "red" }}>加载失败:{error}</div>; return ( <div> <b>Transaction Status:</b> {transaction.status} <br /> {/* 访问深层嵌套属性时用可选链?.避免中间值不存在报错,比如: {transaction?.result?.details?.[0]?.vouchers?.[0]?.result} */} </div> ); } export default Transaction;
核心知识点
- Fetch API默认只有网络故障、跨域等问题才会标记为Promise reject,4xx、5xx类的HTTP错误依然会正常进入
then链,必须手动判断response.ok字段(状态码200-299时为true)抛出错误,才能被catch捕获。 - Promise链式调用时,每个
then回调的返回值会作为下一个then的入参,不要在链中间插入无返回值的逻辑打断参数传递;catch要放在链的末尾,才能捕获前面所有环节抛出的错误,不要提前写catch吞错。 - 所有前端异步请求场景都要维护三类状态:加载中、请求失败、请求成功,根据状态渲染对应内容,不要在数据未返回时直接访问异步返回的对象属性。
- 访问接口返回的深层嵌套属性时,优先用可选链操作符
?.做安全访问,避免某一层字段不存在导致整个页面崩溃。
内容的提问来源于stack exchange,提问作者Manasseh Codes
相关产品推荐
相关产品推荐

