React点击子组件激活时其余兄弟组件自动取消选中的实现咨询
React 单选进度栏实现方案
核心思路
你之前的第二种思路是正确的,将选中状态提升到父组件维护完全符合React单向数据流原则:数据从父组件通过props向下流向子组件,子组件通过父组件传递的回调函数向上传递操作意图,父组件更新状态后重新下发props,整个流程单向可控,是React官方推荐的兄弟组件通信方案。
你之前的代码存在两个核心问题:
- 子组件各自维护独立的选中状态,父组件无法感知也无法同步其他子组件的状态
- 子组件点击逻辑存在冗余错误,连续两次
setState的写法不符合异步更新规则
修正后完整代码
父组件 ProgressBar
class ProgressBar extends React.Component { constructor(props) { super(props); // 父组件统一维护当前选中的进度项类型,默认选中第一个pattern this.state = { selectedType: "pattern" } this.handleSelect = this.handleSelect.bind(this); } // 接收子组件传递的选中类型,更新父组件状态 handleSelect(type) { this.setState({ selectedType: type }) } render() { return <div className="d-flex custom-progress-bar"> <ProgressElement eleType="pattern" isSelected={this.state.selectedType === "pattern"} onSelect={this.handleSelect} /> <ProgressElement eleType="gift" isSelected={this.state.selectedType === "gift"} onSelect={this.handleSelect} /> <ProgressElement eleType="personal" isSelected={this.state.selectedType === "personal"} onSelect={this.handleSelect} /> </div> } }
子组件 ProgressElement
class ProgressElement extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick() { // 点击时调用父组件传递的回调,将自身类型传递给父组件 this.props.onSelect(this.props.eleType); } render() { let eleNumber = NaN; if (this.props.eleType === "pattern") eleNumber = 1; if (this.props.eleType === "gift") eleNumber = 2; if (this.props.eleType === "personal") eleNumber = 3; // 选中状态完全由父组件传递的isSelected prop控制 return <div className={`square-box ${this.props.isSelected ? 'selected' : ''}`} onClick={this.handleClick} > {eleNumber} </div> } }
逻辑说明
- 父组件维护唯一的选中状态源,避免了多个子组件状态不同步的问题
- 子组件完全成为受控组件,只负责视图渲染和点击事件触发,不需要维护内部状态
- 点击任意子组件时,父组件更新选中状态后自动重新渲染所有子组件,仅当前点击的子组件会拿到
isSelected=true的属性,其余自动变为未选中状态,满足单选需求
内容的提问来源于stack exchange,提问作者Flo
相关产品推荐
相关产品推荐

