React传递ID后商品详情无法渲染,报'undefined is not an object'错误
问题分析与解决方案
问题描述
React项目渲染商品详情页时抛出错误:undefined is not an object (evaluating 'product.title')。当把Fixture中的数字类型id改为字符串类型后,详情页可正常显示,但Django REST API(DRF)返回的id仅支持数字类型。
问题根源
核心原因是类型不匹配:
- DRF返回的商品
id是数字类型(例如1) - React Router的
useParams()获取到的URL参数id是字符串类型(例如"1") - 在
Detail.js中使用products.find((product) => product.id === id)时,===是严格全等匹配,数字与字符串类型不相等,导致无法找到匹配的商品,最终product变量为undefined,访问product.title就会触发报错。
修复方案
推荐优先使用方案1(保持严格匹配的严谨性):
方案1:将URL参数转为数字类型
在Detail.js中把字符串类型的id转换为数字后再进行匹配,同时增加空值判断避免渲染报错:
function Detail() { const { id } = useParams(); // 转换URL参数为数字类型 const productId = Number(id); const { product } = useProduct( ({ state: { products } }) => ({ product: products.find((product) => product.id === productId), }), true ); // 处理商品不存在的情况 if (!product) { return <div>商品不存在或已下架</div>; } return ( <div> <h1>{product.title}</h1> <p>Price: ${product.price}</p> <p>{product.overview}</p> </div> ) }
方案2:使用非严格匹配(==)
如果不想做类型转换,可以将严格全等===改为非严格全等==,它会自动进行类型转换后匹配:
const { product } = useProduct( ({ state: { products } }) => ({ product: products.find((product) => product.id == id), }), true );
⚠️ 注意:这种方式不够严谨,可能出现意料外的匹配(例如1 == "1"、0 == false),仅临时场景使用。
额外优化建议
在Product.js中同样增加product空值判断,避免数据加载过程或异常情况下的报错:
function Product({ id }) { const { product } = useProduct( ({ state: { products } }) => ({ product: products.find((product) => product.id === id), }), true ); if (!product) { return <div className='col-3'>加载中...</div>; } return ( <div className='col-3'> {/* 原组件渲染内容 */} </div> ); }
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

