React.js中无法在Props上调用toLocaleString()的问题求助
问题分析与解决
核心问题
- 初始状态类型不匹配:父组件
ItemDetailContainer中product初始值设为数组[],但实际接口返回的是对象结构,导致子组件首次渲染时data.price不存在。 - 异步数据未加载完成就渲染:Firestore的
getDoc是异步操作,组件挂载后会先以初始状态渲染子组件,此时还未拿到后端数据,触发Cannot read properties of undefined错误。
修复步骤
1. 修正父组件初始状态与渲染逻辑
把product的初始值改为null,并在数据加载完成前展示加载状态:
const ItemDetailContainer = () => { // 初始值改为null,明确未加载状态 const [product, setProduct] = useState(null); const { id } = useParams(); useEffect(() => { const querydb = getFirestore(); const querydoc = doc(querydb, 'products', id); getDoc(querydoc) .then(res => setProduct({ id: res.id, ...res.data() })) // setState是异步操作,直接打印res数据而非product .then(() => console.log({ id: res.id, ...res.data() })) }, [id]) // 依赖项添加id,确保路由参数变化时重新请求数据 return ( <div> {/* 数据加载完成后再渲染子组件 */} {product ? <ItemDetail data={product} /> : <div>加载中...</div>} </div> ) } export default ItemDetailContainer
2. 子组件增加防御性处理
在子组件中添加兜底判断,避免因数据缺失导致崩溃:
const ItemDetail = ({ data }) => { const [goToCart, setGoToCart] = useState(false); const { addProduct } = useCartContext() const onAdd = (value) => { value > 0 && setGoToCart(true); addProduct(data, value) } // 数据未加载完成时返回加载提示 if (!data) return <div>加载中...</div> return ( <div className='itemDetailBox'> <div> <img src={data.img_url} className='itemDetailImg' alt="Imagen de producto"></img> </div> <div className='ItemDetailTextBox'> <h2 className='itemDetailTitle'>{data.title || '无标题'}</h2> {/* 用可选链操作符避免price不存在时报错 */} <p className='itemDetailPrice'>${data.price?.toLocaleString() || 0}</p> <p className='ietmDetailDescription'>{data.description || '暂无描述'}</p> { goToCart ? <> <Link to='/'> <button className='btn'>Seguir Comprando</button></Link> <Link to='/cart'> <button className='btn'>Finalizar Compra</button></Link> </> : <ItemCount initial={1} stock={10} onAdd={onAdd}/> } </div> </div> ) }
关键优化点
- 可选链操作符
?.:data.price?.toLocaleString()会在price不存在时直接返回undefined,避免触发类型错误。 - 初始状态匹配数据结构:确保初始状态和后端返回的数据类型一致(对象而非数组)。
- 加载状态提示:在数据未加载完成时展示友好提示,提升用户体验。
内容的提问来源于stack exchange,提问作者Sebastian Pallero Oría
相关产品推荐
相关产品推荐

