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

ReactJS中访问重复组件状态及按钮互斥控制问题

解决React组件间状态同步与按钮禁用问题

嘿,我来帮你搞定这个问题!首先得说,你之前用document.getElementById直接操作DOM导致按钮失效,核心原因是React是状态驱动UI的框架,直接修改DOM会破坏React虚拟DOM和真实DOM的一致性,导致状态和UI脱节。咱们换一种符合React思维的方式来实现需求。

核心思路:状态提升 + 组件通信

既然多个Sharings组件之间需要互相影响(选中一个的单选后,禁用其他的按钮),我们需要把控制按钮禁用的状态提升到父组件,由父组件统一管理,再通过props把状态传递给每个子组件,这样就能避免DOM操作,让React自己维护UI状态。

具体实现步骤

1. 父组件改造:添加全局选中状态

在渲染Sharings的父组件中,新增一个状态selectedSharingIndex,用来记录当前被选中的组件索引(比如0、1、2对应三个组件):

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sharing: {...}, // 你原有的sharing状态
      selectedSharingIndex: null // 初始值为null,表示没有组件被选中
    };
  }

  // 子组件触发的选中回调,更新全局选中索引
  handleSharingSelect = (index) => {
    this.setState({ selectedSharingIndex: index });
  }

  render() {
    return (
      <div className="row">
        {Object.keys(this.state.sharing).map((share, index) => (
          <Sharings
            key={share}
            num={index}
            heading={/* 你的heading数据 */}
            rent={/* 你的rent数组 */}
            details={/* 你的details文本 */}
            // 告诉子组件是否是当前选中的组件
            isSelected={this.state.selectedSharingIndex === index}
            // 传递选中回调给子组件
            onSelect={() => this.handleSharingSelect(index)}
          />
        ))}
      </div>
    );
  }
}

2. 子组件Sharings改造:依赖props控制按钮状态

修改子组件,去掉DOM操作逻辑,改用父组件传递的props来控制按钮禁用状态,同时修复单选按钮的name冲突问题(之前所有单选name都是radio,会导致三个组件的单选互斥,这应该不是你想要的):

class Sharings extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedRent: null // 子组件自己维护选中的rent值
    };
  }

  handleChange = (rent) => {
    // 更新当前组件选中的rent
    this.setState({ selectedRent: rent });
    // 通知父组件:当前组件被选中了
    this.props.onSelect();
  }

  proceed = () => {
    // 按钮点击逻辑,比如获取选中的rent
    console.log("选中的租金:", this.state.selectedRent);
    // 你的其他业务逻辑...
  }

  render() {
    const { props } = this;
    return (
      <div className="col-xs-12 col-md-4">
        <div className="book-now-card p-b-10" style={{height: 'auto'}}>
          <div className="single-sharing" style={{height: '180px'}}>
            <h3 className="single-sharing-heading">{props.heading}</h3>
          </div>
          <div className="m-t-20">
            {props.rent.map((rent) => (
              <div className="m-10" key={rent}>
                <input
                  type="radio"
                  // 给每个组件的单选按钮设置唯一name,避免跨组件互斥
                  name={`radio-group-${props.num}`}
                  className="m-l-20"
                  onClick={() => this.handleChange(rent)}
                  // 显示当前选中的单选按钮状态
                  checked={this.state.selectedRent === rent}
                />
                <span className="m-l-20" style={{color:'#009688'}}>₹ {rent}</span>
                <p className="m-l-55 f-s-12" style={{color: '#65747a'}}>{props.details}</p>
              </div>
            ))}
          </div>
          <div className="m-20">
            <button
              className="btn btn-secondary col-6 select-rent"
              // 只有当前选中的组件,按钮才启用
              disabled={!props.isSelected}
              onClick={this.proceed}
              id={`Button${props.num}`}
            >SELECT</button>
          </div>
        </div>
      </div>
    );
  }
}

关键要点说明

  • 避免DOM操作:通过父组件传递的isSelected props直接控制按钮的disabled状态,完全由React管理UI,不会出现状态不一致的问题。
  • 单选按钮name唯一:给每个组件的单选按钮组设置唯一的name(比如radio-group-${props.num}),保证每个组件内的单选是独立的,不会互相干扰。
  • 组件间通信:通过父组件的回调函数onSelect,子组件可以通知父组件自己被选中,父组件更新全局状态后,再把状态传递给所有子组件,实现联动效果。

这样改造后,当你点击第二个Sharings组件的单选按钮时,父组件会把selectedSharingIndex设为1,此时只有第二个组件的isSelected为true,按钮启用;第一个和第三个组件的isSelected为false,按钮自动禁用,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:59:38