React组件渲染图片报错 自定义Hook拉取接口数据场景咨询
问题结论
该报错和缺少babel、webpack插件没有任何关联,属于前端渲染逻辑与初始值、接口返回格式不匹配导致的JS取值错误。
问题根因
初始值判断逻辑错误
你在useGetProducts自定义Hook中将products的初始值设置为空数组[],而JavaScript中空数组的布尔转换结果为true。组件首次渲染时接口请求还未返回,data.products为初始空数组,会直接进入商品内容渲染分支,此时你尝试读取data.products.images得到undefined,再继续读取[0]下标就会触发Cannot read properties of undefined的报错。两个组件的场景差异
- 正常运行的
ProductItem组件接收父组件传入的product参数,父组件一般会等列表接口返回完整商品数组后,遍历传入单个合法商品对象,同时组件本身也做了product ?的存在性判断,不会出现提前读取空值的问题。 - 报错的
ProductDetail调用的是单个商品详情接口,接口返回值是单个商品对象而非数组,你用空数组做初始值本身就和接口返回格式不匹配,再加上空数组的truthy特性,直接触发了提前渲染的问题。
补充:如果是缺少图片处理的webpack/loader插件,或者图片资源加载失败,只会出现图片裂图的表现,不会触发JS运行时报错阻断整个组件渲染。
修复方案
- 优化自定义Hook初始值
将products的初始值从空数组改为null,null为falsy值,初始渲染时会正确走入加载中的分支:
// useGetProducts 中修改对应代码 const [products, setProducts] = useState(null)
- 优先用Hook返回的
loaded字段做加载判断,不要靠数据本身的truthy判断,同时增加可选链做兜底容错,避免异常数据导致白屏:
// ProductDetail 组件修改后 function ProductDetail() { const data = useGetProducts(`${API}/6`); return ( <> {data.loaded ? ( data.error ? <p>商品加载失败:{data.error}</p> : <> <h3>{data.products?.title}</h3> <p>{data.products?.description}</p> <div> <img src={data.products?.images?.[0]} alt={data.products?.title} /> </div> </> ) : <h4>Loading...</h4>} </> ); }
- (可选)如果这个Hook同时要给商品列表接口用,可以在拿到响应数据后先判断是数组还是对象再做对应赋值,不过更推荐拆分列表和详情的Hook,逻辑更清晰不容易混淆。
内容的提问来源于stack exchange,提问作者alejandro
相关产品推荐
相关产品推荐

