TypeScript中useEffect请求接口渲染数据及对象解构问题
React + TypeScript 接口请求代码修复与对象解构说明
现有代码存在的问题
useState未指定数据类型,TS默认将data推断为undefined类型,后续访问data.landingPageUrl会直接报类型错误- 加载状态判断处存在语法笔误:
if (isLoading=)多写了等号,正确写法为if (isLoading) response.json()本身已经返回Promise结果,后续await responseJson.response属于多余写法,普通对象不需要加await- 初始状态下
data无有效值,直接访问其属性会触发运行时空值错误
TypeScript 对象解构写法
TS完全兼容JS原生的对象解构语法,仅需要提前给被解构的对象定义对应类型即可,你在JS中习惯的const { name, id } = data写法在TS中可以直接使用,常见用法如下:
- 首先根据接口返回结构定义TS类型,和JSON结构一一对应:
// 嵌套的Job字段类型 interface JobType { name: string; designation: string; } // 接口返回的业务数据类型 interface ProductDataType { landingPageUrl: string; name: string; Job: JobType; }
- 基础解构写法和JS完全一致:
// 假设data是ProductDataType类型 // 解构顶层字段 const { landingPageUrl, name } = data; // 解构嵌套字段,可对重名字段起别名 const { Job: { name: companyName, designation } } = data;
- 针对可能为空的对象,可添加兜底值和字段默认值避免报错:
// data可能为null/undefined时,用空对象兜底,同时给字段设置默认值 const { landingPageUrl = '', name = '' } = data ?? {};
你现有代码中
const { id } = useParams<ParamTypes>()本身就是标准的TS对象解构写法,不需要额外调整。
修复后可直接运行的完整代码
import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; interface ParamTypes { id: string; } // 定义接口返回数据类型 interface JobType { name: string; designation: string; } interface ProductDataType { landingPageUrl: string; name: string; Job: JobType; } const SingleProductPage = () => { const { id } = useParams<ParamTypes>(); // 给useState传入泛型指定数据类型,初始值设为null const [data, setData] = useState<ProductDataType | null>(null); const [isLoading, setIsLoading] = useState(false); const fetchProduct = async () => { setIsLoading(true); try { const response = await fetch("myAPIEndpoint"); const responseJson = await response.json(); // 直接取response字段即可,不需要额外加await setData(responseJson.response); } catch (err) { console.error("请求失败:", err); } finally { setIsLoading(false); } }; useEffect(() => { fetchProduct(); }, [id]); if (isLoading) { return <h1>Loading</h1>; } // 空值兜底,data不存在时展示提示 if (!data) { return <h1>数据加载失败</h1> } // 这里可以直接解构使用字段 const { landingPageUrl, name } = data; console.log(landingPageUrl, name); return <h1>Loaded - {landingPageUrl}</h1>; }; export default SingleProductPage;
内容的提问来源于stack exchange,提问作者Rakesh
相关产品推荐
相关产品推荐

