React/TypeScript按钮组添加移除类名的正确实现方法
你当前的问题是每个ActiveBtn组件都独立维护了一套布尔类型的激活状态,不同组件实例的状态完全隔离,因此无法实现同组按钮互斥激活的效果。要实现同一时间仅一个按钮激活的效果,需要将激活状态从单个按钮组件提升到按钮组的父层级统一管理。
改造步骤
1. 优化基础Button组件(可选,仅修复冗余类型定义)
import React from 'react'; import './Button.scss'; interface ButtonProps { children: React.ReactNode; onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; variant: string; className?: string; } const Button: React.FunctionComponent<ButtonProps> = (props: ButtonProps) => { return ( <button type="button" onClick={props.onClick} className={`btn-${props.variant} ${props.className || ''}`} > {props.children} </button> ) } export default Button;
2. 封装统一管理状态的ButtonGroup组件
通过唯一ID标记每个按钮,在组层级统一记录当前激活的按钮ID,点击时切换ID即可自动实现互斥效果:
import React from 'react'; import Button from './Button'; interface ButtonGroupItem { id: string | number; // 每个按钮的唯一标识 label: React.ReactNode; } interface ButtonGroupProps { items: ButtonGroupItem[]; defaultActiveId?: string | number; onChange?: (activeId: string | number) => void; } const ButtonGroup: React.FC<ButtonGroupProps> = (props) => { const { items, defaultActiveId, onChange } = props; const [activeId, setActiveId] = React.useState(defaultActiveId ?? items[0]?.id); const handleClick = (id: string | number) => { setActiveId(id); onChange?.(id); // 原有alert逻辑可放在此处,或通过onChange自定义业务逻辑 } return ( <div className="button-group"> {items.map(item => ( <Button key={item.id} variant={activeId === item.id ? 'tertiary-active' : 'tertiary'} onClick={() => handleClick(item.id)} > {item.label} </Button> ))} </div> ) } export default ButtonGroup;
3. 业务组件中调用
const Page = () => { // 示例:渲染3个互斥激活的按钮 return ( <ButtonGroup items={[ { id: 'btn1', label: '按钮1' }, { id: 'btn2', label: '按钮2' }, { id: 'btn3', label: '按钮3' } ]} defaultActiveId="btn1" onChange={(activeId) => console.log('当前激活按钮ID:', activeId)} /> ) }
如果不需要封装通用按钮组,也可以直接在父组件声明激活状态,逐个传给Button组件即可:
const Page = () => { const [activeId, setActiveId] = React.useState('btn1'); return ( <div> <Button variant={activeId === 'btn1' ? 'tertiary-active' : 'tertiary'} onClick={() => setActiveId('btn1')} > 按钮1 </Button> <Button variant={activeId === 'btn2' ? 'tertiary-active' : 'tertiary'} onClick={() => setActiveId('btn2')} > 按钮2 </Button> <Button variant={activeId === 'btn3' ? 'tertiary-active' : 'tertiary'} onClick={() => setActiveId('btn3')} > 按钮3 </Button> </div> ) }
内容的提问来源于stack exchange,提问作者Sole
相关产品推荐
相关产品推荐

