You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 07:45:37