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

React中如何禁用/启用绑定父组件回调函数的子组件按钮

解决方案

核心问题分析

原来的代码里,doOperation是异步操作但没返回Promise,子组件调用后立刻执行setDisabled(false),导致按钮刚禁用就马上恢复,达不到预期效果。另外如果两个按钮共用同一个disabled状态,点击其中一个会同时禁用两个按钮,可根据需求选择单独控制或统一控制。

步骤1:改造父组件的异步函数

让doOperation返回Promise,这样子组件可以等待异步操作完成:

export default function App() {
  const [val, setVal] = useState(0);
  // 修改为返回Promise的函数,操作完成后通知子组件
  const doOperation = (qty) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        setVal((prev) => prev + qty);
        resolve();
      }, 5000);
    });
  };

  return (
    <div className="App">
      <input placeholder={val} />
      <div style={{ display: "flex" }}>
        <ChildButtons qty={1} doOperation={doOperation} />
        {/* 模拟滚动列表场景,添加多个列表项 */}
        <ChildButtons qty={2} doOperation={doOperation} />
        <ChildButtons qty={3} doOperation={doOperation} />
      </div>
    </div>
  );
}

步骤2:子组件处理按钮禁用逻辑

根据需求选择以下两种方案:

方案A:每个按钮单独控制禁用状态

点击+按钮仅禁用自身,-按钮可正常操作,反之亦然:

const ChildButtons = ({ qty, doOperation }) => {
  const [disableAdd, setDisableAdd] = useState(false);
  const [disableSubtract, setDisableSubtract] = useState(false);

  const handleAdd = async () => {
    setDisableAdd(true);
    await doOperation(qty);
    setDisableAdd(false);
  };

  const handleSubtract = async () => {
    setDisableSubtract(true);
    await doOperation(-1 * qty);
    setDisableSubtract(false);
  };

  return (
    <div style={{ margin: "0 10px" }}>
      <button onClick={handleAdd} disabled={disableAdd}>
        + {qty}
      </button>
      <button onClick={handleSubtract} disabled={disableSubtract} style={{ marginLeft: "5px" }}>
        - {qty}
      </button>
    </div>
  );
};

方案B:子组件内两个按钮共用禁用状态

点击任意一个按钮,当前列表项的两个按钮都禁用,直到操作完成:

const ChildButtons = ({ qty, doOperation }) => {
  const [disabled, setDisabled] = useState(false);

  const handleOperation = async (operateQty) => {
    setDisabled(true);
    await doOperation(operateQty);
    setDisabled(false);
  };

  return (
    <div style={{ margin: "0 10px" }}>
      <button onClick={() => handleOperation(qty)} disabled={disabled}>
        + {qty}
      </button>
      <button onClick={() => handleOperation(-1 * qty)} disabled={disabled} style={{ marginLeft: "5px" }}>
        - {qty}
      </button>
    </div>
  );
};

关键说明

  • 父组件的doOperation必须返回Promise,确保子组件能精准等待异步操作结束,避免按钮提前恢复可用。
  • 滚动列表场景下,每个ChildButtons组件独立维护自身状态,多个列表项的按钮禁用逻辑互不干扰,完全适配动态数量的列表项需求。

内容的提问来源于stack exchange,提问作者SJaka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:50:19