如何通过复用<Button/>组件处理多按钮的加载/禁用状态与点击逻辑
复用按钮组件实现单按钮加载、其余禁用的方案
核心思路是把加载状态的控制权从子组件收回到父组件,用唯一标识追踪当前加载中的按钮,让单个通用按钮组件根据这个标识自动判断自身状态,既减少代码冗余,又满足需求。
1. 定义通用按钮组件
创建可复用的<ApiButton>组件,通过接收props来区分不同按钮的状态和行为:
import { Button } from 'your-ui-library'; // 替换为你使用的UI库(如Antd、MUI) const ApiButton = ({ buttonKey, loadingKey, onClick, children }) => { const isLoading = loadingKey === buttonKey; // 禁用规则:有按钮在加载且不是当前按钮,或当前按钮正在加载(防止重复点击) const isDisabled = !!loadingKey && !isLoading; const handleClick = async () => { await onClick(); }; return ( <Button onClick={handleClick} loading={isLoading} disabled={isDisabled || isLoading} > {isLoading ? '加载中...' : children} </Button> ); }; export default ApiButton;
2. 父组件中使用通用按钮
父组件维护全局加载状态,给每个按钮分配唯一标识,并传入对应的API请求逻辑:
import { useState } from 'react'; import ApiButton from './ApiButton'; const ParentComponent = () => { // 记录当前正在加载的按钮标识,初始为null表示无加载状态 const [loadingButtonKey, setLoadingButtonKey] = useState(null); // 模拟接口请求1 const fetchData1 = async () => { setLoadingButtonKey('btn1'); try { await new Promise(resolve => setTimeout(resolve, 2000)); // 模拟接口延迟 console.log('接口1请求完成'); } catch (err) { console.error('接口1请求失败', err); } finally { setLoadingButtonKey(null); // 请求结束后重置状态 } }; // 模拟接口请求2 const fetchData2 = async () => { setLoadingButtonKey('btn2'); try { await new Promise(resolve => setTimeout(resolve, 2000)); console.log('接口2请求完成'); } catch (err) { console.error('接口2请求失败', err); } finally { setLoadingButtonKey(null); } }; return ( <div style={{ gap: '10px', display: 'flex', padding: '20px' }}> <ApiButton buttonKey="btn1" loadingKey={loadingButtonKey} onClick={fetchData1}> 调用接口1 </ApiButton> <ApiButton buttonKey="btn2" loadingKey={loadingButtonKey} onClick={fetchData2}> 调用接口2 </ApiButton> {/* 新增按钮只需添加唯一buttonKey和对应API函数即可 */} </div> ); }; export default ParentComponent;
方案优势
- 完全复用单个按钮组件,新增按钮无需创建新组件,大幅减少冗余代码
- 加载状态统一在父组件管理,避免子组件状态分散导致的同步问题
- 禁用和加载逻辑集中在通用组件,后续修改只需维护一处代码
内容的提问来源于stack exchange,提问作者nikkbh
相关产品推荐
相关产品推荐

