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

React Bootstrap ToggleButton点击时handlePlatformChange函数触发两次求助

解决React-Bootstrap ToggleButton点击时函数触发两次的问题

我之前也碰到过这个一模一样的问题,核心原因是你误用了原生的onClick事件来处理ToggleButton的选中状态变更——react-bootstrap的ToggleButtonGroup和ToggleButton是受控组件,它们有自己的状态管理机制,应该用组件提供的onChange事件来处理选中状态,而不是直接监听原生点击事件。

为什么会触发两次?

当你点击ToggleButton时,会发生两个连锁过程:

  1. 原生点击事件先触发,此时e.target是按钮元素,能正确获取到id,所以第一次调用handlePlatformChange时传递了正确的值。
  2. ToggleButton组件内部会更新自身的选中状态(比如添加/移除active类),这个过程中会触发组件内部的状态更新逻辑,可能导致事件冒泡或重复触发,此时e.target可能变成了组件内部的其他元素,所以第二次调用时拿到的是null。

而添加e.preventDefault()会直接阻止组件的默认切换行为,这就导致按钮无法正常切换选中状态,显然不是我们想要的结果。

解决方案:使用ToggleButtonGroup的onChange事件

我们可以利用ToggleButtonGroup提供的onChange事件来统一处理选中状态的变更,它会直接返回选中的value,我们只需要把value映射到对应的platform id即可。

修改后的完整代码

import React, {Component} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Button from 'react-bootstrap/Button';
import ToggleButton from 'react-bootstrap/ToggleButton';
import ToggleButtonGroup from 'react-bootstrap/ToggleButtonGroup';

class App extends Component {
  constructor () {
    super();
    this.state = {
      User : "",
      Platform: "battle",
      Player: "",
      Level: ""
    };
    this.handleChange = this.handleChange.bind(this);
    // 新增:创建value到platform id的映射表
    this.valueToPlatform = {
      1: "battle",
      2: "acti",
      3: "psn",
      4: "xbl"
    };
  }

  // 修改:处理ToggleButtonGroup的onChange事件,直接接收选中的value
  handlePlatformChange = (selectedValue) => {
    const platformId = this.valueToPlatform[selectedValue];
    this.setState({Platform: platformId}, function () {
      console.log(this.state.Platform);
    });
  }

  handleChange(e) {
    if (e.target.id === "usernameinput") {
      this.setState({User: e.target.value});
    }
  }

  render() {
    return (
      <div className="infoSection">
        <div className="center">
          <input type="text" id="usernameinput" value={this.state.value} onChange={this.handleChange} placeholder="Username" /><br/>
          {/* 修改:在ToggleButtonGroup上绑定onChange,移除单个ToggleButton的onClick */}
          <ToggleButtonGroup 
            id="buttongroup" 
            name="buttongroup" 
            defaultValue={1}
            onChange={this.handlePlatformChange}
          >
            <ToggleButton id="battle" value={1} variant="secondary"></ToggleButton>
            <ToggleButton id="acti" value={2} variant="secondary"></ToggleButton>
            <ToggleButton id="psn" value={3} variant="secondary"></ToggleButton>
            <ToggleButton id="xbl" value={4} variant="secondary"></ToggleButton>
          </ToggleButtonGroup>
          <br/>
          <Button id="searchButton" variant="primary">Search</Button>
          <div className="displaySection">
            <p id="displayHeader">Username: {this.state.Player}<br/>
              Level: {this.state.Level}</p>
            <p id="displayInfo1">some info here</p>
            <p id="displayInfo1">some info here</p>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

关键修改说明

  1. 新增value映射表:valueToPlatform把ToggleButton的数字value转换成你需要的字符串id(比如1对应"battle"),让状态更新更直观。
  2. 重写handlePlatformChange:现在它直接接收选中的value参数,不需要再依赖事件对象,避免了e.target变化的问题。
  3. 绑定ToggleButtonGroup的onChange:移除每个ToggleButton上的onClick,把事件处理逻辑统一移到父组件ToggleButtonGroup上,这样只会在选中状态变更时触发一次,完美解决重复触发的问题。

这样修改后,每次点击ToggleButton只会触发一次状态更新,按钮也能正常切换选中状态,state里的Platform也会正确设置为对应的id。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:30:29