React实现加入购物车按钮报buttonText未定义TypeError排查
报错根因
你触发的TypeError: Cannot set properties of undefined (setting 'buttonText')和按钮文案不更新问题,由3个代码逻辑错误直接导致:
- 状态初始化时机错误:
useState(props.products)仅在组件首次挂载时执行一次赋值。如果组件首次挂载时父组件还未完成fetch请求、传入的products是空数组/undefined,本地statebuttonText会永久保留初始空值,后续props更新不会自动同步到这个state中。点击事件触发时,你对空值做深拷贝得到的是空数组,访问testing[index]得到undefined,给undefined对象赋值属性就会抛出你看到的错误。 - 渲染数据源错误:组件return中遍历渲染始终使用
props.products,哪怕你正确更新了本地state,视图读取的还是props里的原始值,按钮文案永远不会变化。 - 兜底逻辑无效:你写的
const testing = newText || []仅在newText本身是null/undefined时才会兜底为空数组,如果newText是空数组(属于真值),兜底逻辑不会触发,此时访问数组的任意索引都会得到undefined。
可直接运行的修复代码
import React, { useState, useEffect } from "react"; import "../sass/layout/_grid.scss"; import "../sass/components/_product-card.scss"; import "../sass/components/_buttons.scss"; export interface ProductProps { products: { id: number; name: string; price: number; desc: string; img: string; units: number; buttonText: string; }[]; } const ProductCard: React.FC<ProductProps> = (props) => { // 初始值加空数组兜底,避免首次挂载无数据时报错 const [productList, setProductList] = useState(props.products || []); // 监听props变化,fetch完成拿到数据后自动同步到本地state useEffect(() => { setProductList(props.products || []); }, [props.products]); const handleClick = (index: number) => { // 用扩展运算符做浅拷贝,替代JSON序列化的低性能写法 const newList = [...productList]; // 操作前判断索引项是否存在,彻底避免数组越界 if (newList[index]) { newList[index] = { ...newList[index], buttonText: "Adding to cart..." }; setProductList(newList); setTimeout(() => { // 仅重置当前点击按钮的文案,不影响其他商品 const resetList = [...newList]; resetList[index] = { ...resetList[index], buttonText: "add to cart" }; setProductList(resetList); }, 2000); } }; return ( <> {productList.length > 0 && productList.map((it, index) => ( <article key={it.id} className="product-card"> <img src={it.img} alt={it.name} /> <h3>{it.name}</h3> <p>{it.desc}</p> <h4>{it.price}.00€</h4> <div className="product-card__button--wrapper"> <button className="product-card-button" onClick={() => { handleClick(index); console.log(it.id); }} > {it.buttonText} </button> <button className="product-card-button">info</button> </div> </article> ))} </> ); }; export default ProductCard;
关键修复点说明
- 给state初始值增加空数组兜底,组件首次挂载哪怕props未传值也不会出现undefined异常
- 新增
useEffect监听props.products变化,fetch请求完成后自动同步数据到本地state,解决初始值为空导致的数组越界问题 - 替换JSON深拷贝为扩展运算符浅拷贝,符合React状态更新规范,避免大列表下的性能损耗
- 数组操作前增加索引项存在性判断,从根源上避免给undefined赋值的报错
- 渲染时遍历本地state存储的商品列表,状态更新后按钮文案可以实时响应变化
- 移除按钮上多余的key属性(key仅需加在遍历的最外层article元素上即可,内层子元素无需重复添加)
- 定时器逻辑调整为仅重置当前点击按钮的文案,多商品点击时不会互相干扰
内容的提问来源于stack exchange,提问作者danipereiracodes
相关产品推荐
相关产品推荐

