React中如何在map遍历的单个元素内通过onClick修改状态
解决React卡片点击仅展示当前卡片状态的问题
核心思路是用「激活的产品ID」替代全局布尔值,精准控制单个卡片的显示状态,同时用对象存储每个产品的购买次数,避免重复请求。
步骤1:调整状态定义
把原来的isShown换成记录当前激活产品的ID,再新增一个对象存储各产品的购买次数:
const [activeProductId, setActiveProductId] = useState<number | null>(null); const [purchasedCounts, setPurchasedCounts] = useState<Record<number, number>>({});
步骤2:修改点击事件处理函数
在点击时获取对应产品的购买次数,更新存储对象,并切换当前激活的产品ID:
const handleClick = async (id: number) => { // 如果当前已经显示该产品,点击则隐藏 if (activeProductId === id) { setActiveProductId(null); return; } // 如果已经获取过该产品的次数,直接显示,不用重复请求 if (purchasedCounts[id]) { setActiveProductId(id); return; } // 异步获取购买次数(假设getAmountOfTimesPurchased是异步函数) const count = await getAmountOfTimesPurchased(id); setPurchasedCounts(prev => ({ ...prev, [id]: count })); setActiveProductId(id); };
步骤3:修改卡片渲染逻辑
只有当当前卡片的ID和激活ID匹配时,才显示对应的购买次数:
return ( <div> {products.map((product: IProduct) => { return ( <Card key={product.id}> <Card.Body> <Card.Text> <Card.Title>{product.name}</Card.Title> ${product.price} <br /> {product.amount} </Card.Text> </Card.Body> <Card.Footer> <Button onClick={() => handleClick(product.id)}> Purchased For: </Button> {activeProductId === product.id && purchasedCounts[product.id]} </Card.Footer> </Card> ); })} </div> );
补充说明
- 如果
getAmountOfTimesPurchased是同步函数,去掉async/await即可 - 加入了缓存逻辑,已经获取过的次数不会重复请求,提升性能
- 支持点击同一按钮切换显示/隐藏状态,如果不需要这个功能,删掉
if (activeProductId === id)的判断即可
内容的提问来源于stack exchange,提问作者JavaExplorer
相关产品推荐
相关产品推荐

