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
相关产品推荐
相关产品推荐

