React/NextJS中onClick触发所有映射项,如何仅精准触发点击的单个项?
问题根因
你当前仅声明了一个全局的布尔类型状态isFlipped,所有通过map渲染的卡片元素都共用这同一个状态判断是否要翻转,所以只要状态变更,所有卡片都会同步触发动画效果。
解决方案
将状态修改为存储当前被点击卡片的唯一标识,仅在当前卡片的标识和状态中存储的标识匹配时触发翻转动画,推荐优先使用业务数据中的唯一ID作为标识,实现代码如下:
// 状态改为存储被翻转卡片的唯一ID,初始值为null代表无卡片被翻转 const [flippedId, setFlippedId] = useState(null); const flip = (productId) => { // 重复点击同一张已翻转的卡片则重置为未翻转状态,否则切换为当前点击的卡片 setFlippedId(flippedId === productId ? null : productId); }; return( data.map((product) => ( <div onClick={()=> flip(product.id)} // 仅当前卡片ID匹配时触发翻转动画 animate={flippedId === product.id && { rotateY: 180 }} key={product.id} // React列表渲染必填的key属性,避免渲染异常 > <p>{product.name}</p> <p>{product.info}</p> </div> )); )
临时替代方案(无唯一ID时)
如果你的product数据暂时没有唯一ID字段,可临时使用map遍历的索引作为标识,不推荐长期使用,列表顺序变更时可能导致状态错乱:
const [flippedIndex, setFlippedIndex] = useState(null); const flip = (index) => { setFlippedIndex(flippedIndex === index ? null : index); }; return( data.map((product, index) => ( <div onClick={()=> flip(index)} animate={flippedIndex === index && { rotateY: 180 }} key={index} > <p>{product.name}</p> <p>{product.info}</p> </div> )); )
多卡片同时翻转方案
如果需要支持多张卡片同时保持翻转状态,可将状态改为Set类型存储所有已翻转的卡片ID:
const [flippedIds, setFlippedIds] = useState(new Set()); const flip = (productId) => { const newFlippedIds = new Set(flippedIds); newFlippedIds.has(productId) ? newFlippedIds.delete(productId) : newFlippedIds.add(productId); setFlippedIds(newFlippedIds); }; return( data.map((product) => ( <div onClick={()=> flip(product.id)} animate={flippedIds.has(product.id) && { rotateY: 180 }} key={product.id} > <p>{product.name}</p> <p>{product.info}</p> </div> )); )
内容的提问来源于stack exchange,提问作者Liiaam93
相关产品推荐
相关产品推荐

