You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React刷新页面API数据undefined 读取name属性报错

问题根因
  • 核心是异步请求和组件渲染的时序没对齐:你用的useGetCryptoDetailsQuery是RTK Query提供的异步请求Hook,刷新页面触发组件首次冷渲染时,接口请求还处于等待返回的状态,这时候Hook返回的data默认值为undefined,执行const cryptoDetails = data?.data?.coin得到的结果自然也是undefined。
  • 热更新场景不报错是缓存机制导致的:编辑代码保存触发热更新时,不会清空RTK Query已经缓存的接口返回数据,组件直接复用之前请求成功的缓存值渲染,所以不会触发报错,也就出现了“保存就正常、刷新就报错”的反差。
  • 空值保护逻辑不完整:你只在给cryptoDetails赋值时加了可选链?.,但后续渲染阶段读取cryptoDetails.name、cryptoDetails.slug时没有做任何空值判断,首次渲染时cryptoDetails为undefined,直接读取属性就会抛出如下错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'name')

对应控制台日志截图如下:
控制台日志数据截图

修复方案

以下方案可单独使用,也可组合使用,都能解决问题:

  • 方案1:用Hook返回的isFetching状态做渲染拦截,请求完成、数据确认存在前不渲染详情内容,是最稳妥的实现方式,示例代码:
const CryptoDetails = () => {
  const { coinId } = useParams()
  const [timePeriod, setTimePeriod] = useState('7d')
  const {data, isFetching } = useGetCryptoDetailsQuery(coinId)
  const cryptoDetails = data?.data?.coin
  
  // 加载中或数据不存在时,直接返回加载占位,不走后续详情渲染逻辑
  if (isFetching || !cryptoDetails) {
    return <div>详情加载中...</div>
  }

  return (
    <Col className='coin-detail-container'>
      <Col className='coin-heading-container'>
        <Title level={2} className='coin-name'>
          {cryptoDetails.name} ({cryptoDetails.slug}) Price
        </Title>
        {/* 其余原有渲染逻辑保持不变即可 */}
      </Col>
    </Col>
  )
}
  • 方案2:补全属性读取环节的空值保护,配置兜底展示值,适合不想做整块加载拦截的场景,示例代码:
<Title level={2} className='coin-name'>
  {/* 可选链+空值合并语法,取不到值时展示默认占位 */}
  {cryptoDetails?.name ?? '--'} ({cryptoDetails?.slug ?? '--'}) Price
</Title>
  • 方案3:给cryptoDetails设置默认空对象兜底,从根源避免undefined读取属性的报错:
// 取不到coin数据时默认赋值为空对象,后续读属性不会抛出类型错误
const cryptoDetails = data?.data?.coin ?? {}

内容的提问来源于stack exchange,提问作者Achi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:12:20