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

React按钮组如何实现点击单按钮时其余按钮自动取消激活态?

核心解决思路

你现在的问题是激活状态存在单个ActiveBtn内部,每个按钮的状态独立,自然没法实现互斥效果。只要把激活状态提升到所有按钮的共同父组件层级,用唯一标识(索引/自定义id/按钮名)记录当前激活的按钮,而不是用布尔值存单个按钮的激活状态,就可以实现点一个其他自动取消激活的效果。


步骤1:改造ActiveBtn组件,把状态相关属性提到props

interface ActiveBtnProps {
  // 按钮唯一标识
  btnId: string | number
  // 父组件传入的当前是否激活状态
  isActive: boolean
  // 点击触发的回调,把当前按钮id传给父组件
  onActiveChange: (btnId: string | number) => void
  children: React.ReactNode
}

const ActiveBtn: React.FunctionComponent<ActiveBtnProps> = (props) => {
  const handleClick = () => {
    props.onActiveChange(props.btnId)
  }
  return (
    <Button 
      variant={props.isActive ? 'tertiary-active' : 'tertiary'} 
      onClick={handleClick}
    >
      {props.children}
    </Button>
  )
}

步骤2:在业务父组件里维护激活状态

const BusinessPage: React.FunctionComponent = () => {
  // 状态存当前激活的按钮id,初始值可以设为默认激活的按钮id,没有就设为null
  const [activeBtnId, setActiveBtnId] = React.useState<string | number>('btn1')

  return (
    <div className="btn-group">
      <ActiveBtn 
        btnId="btn1" 
        isActive={activeBtnId === 'btn1'} 
        onActiveChange={setActiveBtnId}
      >
        按钮1
      </ActiveBtn>
      <ActiveBtn 
        btnId="btn2" 
        isActive={activeBtnId === 'btn2'} 
        onActiveChange={setActiveBtnId}
      >
        按钮2
      </ActiveBtn>
      <ActiveBtn 
        btnId="btn3" 
        isActive={activeBtnId === 'btn3'} 
        onActiveChange={setActiveBtnId}
      >
        按钮3
      </ActiveBtn>
    </div>
  )
}

更优的封装方式

如果多个场景都要用到按钮组互斥效果,可以直接封装通用的ButtonGroup组件,把状态逻辑内置,业务方直接传配置即可:

interface ButtonGroupItem {
  id: string | number
  content: React.ReactNode
}
interface ButtonGroupProps {
  items: ButtonGroupItem[]
  defaultActiveId?: string | number
  onChange?: (activeId: string | number) => void
}

const ButtonGroup: React.FunctionComponent<ButtonGroupProps> = (props) => {
  const [activeId, setActiveId] = React.useState(props.defaultActiveId ?? null)

  const handleChange = (id: string | number) => {
    setActiveId(id)
    props.onChange?.(id)
  }

  return (
    <div className="btn-group">
      {props.items.map(item => (
        <Button
          key={item.id}
          variant={activeId === item.id ? 'tertiary-active' : 'tertiary'}
          onClick={() => handleChange(item.id)}
        >
          {item.content}
        </Button>
      ))}
    </div>
  )
}

业务方调用非常简洁:

<ButtonGroup 
  items={[
    {id: 'btn1', content: '按钮1'},
    {id: 'btn2', content: '按钮2'},
    {id: 'btn3', content: '按钮3'},
  ]}
  defaultActiveId="btn1"
  onChange={(id) => console.log('当前激活按钮', id)}
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:48:01