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

React实现单个按钮独立控制折叠展开,避免批量触发

解决单个按钮独立控制对应内容显示的问题

你遇到的核心问题是所有按钮共享同一个全局状态on,所以点击任何一个按钮都会切换这个状态,导致所有隐藏文本一起显示/隐藏。要实现每个按钮独立控制自己的内容,我们需要给每个教堂单独维护展开状态,而不是用一个统一的布尔值。

下面是具体的修改方案:

1. 重构状态结构

把原来单个的on状态,改成一个对象来存储每个教堂的展开状态。比如用教堂的索引(或者更可靠的唯一ID,如果你的教堂对象有id字段的话)作为键,值是布尔值,表示该教堂是否展开:

constructor(props) {
  super(props);
  this.toggle = this.toggle.bind(this);
  this.state = {
    // 用对象存储每个教堂的展开状态,初始默认都是未展开(false)
    expandedChurches: {}
  }
}

2. 修改toggle方法,让它接收标识参数

更新toggle方法,让它接收一个代表当前教堂的标识(比如索引或ID),然后只切换该标识对应的状态:

toggle(churchIndex) {
  // 使用函数式setState,确保基于最新的状态进行更新
  this.setState(prevState => ({
    expandedChurches: {
      // 复制之前的状态,避免直接修改原对象
      ...prevState.expandedChurches,
      // 切换对应教堂的展开状态
      [churchIndex]: !prevState.expandedChurches[churchIndex]
    }
  }));
}

3. 调整渲染逻辑,绑定对应状态

修改createButtonsForChurches函数,主要做三个改动:

  • 把循环里的var i改成let i(避免闭包变量共享的问题)
  • 点击按钮时传入当前教堂的索引
  • 条件渲染时检查当前教堂对应的展开状态
  • 给每个列表项添加key属性(React列表渲染的必填项)
createButtonsForChurches(arr) {
  var listOfButtons = [];
  // 用let声明i,保证每次循环都有独立的变量作用域
  for (let i = 1; i < arr.length; i++) {
    var currentButton = (
      <div key={i}> {/* 添加唯一key,帮助React优化渲染 */}
        {/* 点击时传入当前教堂的索引 */}
        <button onClick={() => this.toggle(i)} className="churchButton">{arr[i].name}</button>
        {/* 检查当前教堂的展开状态,而不是全局的on */}
        { this.state.expandedChurches[i] && (
          <div className="allContent">
            <div className="individualContent">
              {(arr[i].femaleStudents[0]) && this.createContentParagraphTextForArray(arr[i].femaleStudents, "Female Students")}
            </div>
            <div className="individualContent">
              {(arr[i].femaleLeaders[0]) && this.createContentParagraphTextForArray(arr[i].femaleLeaders, "Female Leaders")}
            </div>
            <div className="individualContent">
              {(arr[i].maleStudents[0]) && this.createContentParagraphTextForArray(arr[i].maleStudents, "Male Students")}
            </div>
            <div className="individualContent">
              {(arr[i].maleLeaders[0]) && this.createContentParagraphTextForArray(arr[i].maleLeaders, "Male Leaders")}
            </div>
          </div>
        )}
      </div>
    );
    listOfButtons.push(currentButton);
  }
  return listOfButtons;
}

更可靠的优化:用教堂ID代替索引

如果你的教堂对象有唯一的id字段(比如arr[i].id),建议用id来代替索引作为状态的键,这样即使数组顺序变化,状态也能正确对应到对应的教堂:

// 修改toggle方法
toggle(churchId) {
  this.setState(prevState => ({
    expandedChurches: {
      ...prevState.expandedChurches,
      [churchId]: !prevState.expandedChurches[churchId]
    }
  }));
}

// 渲染时传入id
<button onClick={() => this.toggle(arr[i].id)} className="churchButton">{arr[i].name}</button>

// 条件渲染时检查id对应的状态
{ this.state.expandedChurches[arr[i].id] && (...) }

这样修改后,每个按钮就只会控制自己对应的隐藏文本,实现独立工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:24:53