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

React TypeScript中如何实现支持传入对象数组的可复用ButtonGroup组件

实现思路

核心是把组件内部的「激活状态维护逻辑」和外部传入的「按钮业务逻辑」完全解耦:

  • 激活状态完全由ButtonGroup组件内部自己维护,不需要外部传入的配置携带状态更新函数
  • 外部传入的每个按钮配置里只需要带自身的业务点击回调、id、文案这些业务属性即可
  • 点击按钮时先触发内部状态更新切换激活态,再执行对应按钮绑定的业务回调
调整后的代码

接口定义

先调整接口,把原来的function改名避免和关键字冲突,简化参数定义:

export interface ButtonItem {
  id: number;
  title: string;
  onClick: () => void; // 每个按钮独立的业务执行函数
}

export interface ButtonGroupProps {
  data: ButtonItem[]; // 外部传入的按钮配置数组
  defaultActiveId?: number; // 可选参数,指定默认激活的按钮id,不传默认激活第一个
}

组件实现

import React from 'react';
import { ButtonItem, ButtonGroupProps } from '../../shared/interfaces/ButtonGroup.interface';

const ButtonGroup: React.FunctionComponent<ButtonGroupProps> = ({ 
  data, 
  defaultActiveId 
}) => {
  // 内部维护激活状态,存id比存完整对象更稳定,避免引用对比异常问题
  const [activeId, setActiveId] = React.useState<number>(() => {
    if (defaultActiveId) return defaultActiveId;
    return data[0]?.id ?? 0;
  });

  const getBtnClass = (item: ButtonItem) => {
    return item.id === activeId ? "active" : "not-active";
  };

  const handleBtnClick = (item: ButtonItem) => {
    // 先更新激活状态
    setActiveId(item.id);
    // 再执行按钮绑定的业务函数
    item.onClick();
  };

  return (
    <div className="btn-group">
      {data.map((item) => (
        <button 
          type="button" 
          className={getBtnClass(item)} 
          onClick={() => handleBtnClick(item)} 
          key={item.id}
        >
          {item.title}
        </button>
      ))}
    </div>
  )
}

export default ButtonGroup;

调用方式

父组件调用时只需要传入对应的配置数组即可:

// 父组件内定义按钮配置
const buttonConfig = [
  {
    id: 1,
    title: '按钮1',
    onClick: () => {
      console.log('执行按钮1的业务逻辑')
    }
  },
  {
    id: 2,
    title: '按钮2',
    onClick: () => {
      console.log('执行按钮2的业务逻辑')
    }
  },
  {
    id: 3,
    title: '按钮3',
    onClick: () => {
      console.log('执行按钮3的业务逻辑')
    }
  }
]

// 调用组件
<ButtonGroup data={buttonConfig} />
// 也可以指定默认激活的按钮
// <ButtonGroup data={buttonConfig} defaultActiveId={2} />
可选优化

如果需要父组件控制激活状态,可以额外加activeId props和onChange回调,把激活状态的控制权交给父组件,满足更复杂的业务场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:51:02