React中仅为点击的Add to Bag按钮显示动画的问题求助
问题分析
你当前的问题是所有按钮共用了同一个submitResponse全局状态,点击任意按钮时,这个全局状态的变化会触发所有按钮的动画和禁用状态,导致所有按钮一起响应。
解决方案
核心思路是给每个按钮维护独立的状态,用对象存储每个商品ID对应的提交状态,而非单一的全局状态。
1. 修改状态定义
把全局的submitResponse改成对象,键为商品ID,值为对应状态;去掉addedId,因为状态已经和ID绑定:
// 初始为空对象,每个键是variation的ID,值是{class: "", openState: false} const [submitResponses, setSubmitResponses] = useState({}); const [response, setResponse] = useState();
2. 重构onSubmit函数
让函数接收当前点击的商品ID作为参数,仅更新该ID对应的状态:
const onSubmit = (variationId) => { response .then(() => { // 更新当前ID的成功状态 setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "added", openState: true } })); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "added txtState", openState: true } })); }, 10); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "added", openState: true } })); }, 3000); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "", openState: false } })); }, 3500); }) .catch(() => { // 更新当前ID的失败状态 setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "danger", openState: true } })); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "danger txtState", openState: true } })); }, 10); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "danger", openState: true } })); }, 3000); setTimeout(() => { setSubmitResponses(prev => ({ ...prev, [variationId]: { class: "", openState: false } })); }, 3500); }); };
3. 修正按钮的className和disabled属性
让每个按钮只读取自己ID对应的状态:
<Button id={`Sproduct-btn-${variations.ID}`} {/* 给每个按钮唯一ID,避免DOM重复 */} className={`btn add-to-cart w-100 ${ submitResponses[variations.ID]?.class || "" }`} data-toggle="tooltip" type="button" tag={!user ? Link : "a"} to={!user ? "/login" : ""} disabled={ submitResponses[variations.ID]?.openState || Status === "Inactive" || variationStatus === "Inactive" || Stock === 0 || variationStock === 0 } style={{ fontSize: "15px", width: "30%" }} {...(user && { onClick: () => { setResponse(addToCart(productid, variations.ID)); onSubmit(variations.ID); // 传递当前商品ID }, })} > {/* 按钮内部内容保持不变 */} </Button>
额外说明
- 使用函数式更新状态(
prev => ({...prev, ...})),确保状态更新基于最新的前序状态,避免竞态问题。 - 给每个按钮设置唯一ID,解决原代码中所有按钮ID相同的DOM规范问题。
修改后,每个按钮的状态完全独立,点击目标按钮只会触发该按钮的动画,不会影响其他按钮。
内容的提问来源于stack exchange,提问作者Lucky
相关产品推荐
相关产品推荐

