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
相关产品推荐
相关产品推荐

