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

React中Select2下拉框重选已选项无触发问题求助

React中Select2下拉框重复选择已选项无响应的问题解决

问题描述

我是React新手,开发应用时碰到Select2下拉框的异常问题:searchLedgerNames函数定义在依赖props的useEffect中,下拉框选项变更时useEffect会触发并调用该函数,但重新选择已经选中的项目时,页面完全没有任何反应。

问题代码

组件逻辑部分

useEffect(() => {
  setLedgerDates();
  searchLedgerNames();
  if (props != undefined && props.location.state != undefined) {
      // 设置数据的相关逻辑
   }, [props]);

function searchLedgerNames() {
  
  $('.ledger').select2({
      placeholder: "Select Ledger",
      multiple: false,
      width: '100%',
      tags: false,
      allowClear: true,
      ajax: {
          url: config.searchLedgerNames,
          type: 'GET',
          data: function (params) {
              return {
                  'searchName': params.term,
                  'token': UserInfo.getToken()
              };
          },
         
          processResults: function (data) {
             
              if (data.status == 1) {      
              return {
        
                  results: $.map(data.ledgerMap, function (item) {
                      return {
                          text: item.ledgerName,
                              id: item.supplierOrCustomerId,
                              ledgerType: item.ledgerType
                      }
                  })
              };
          }
      }
      },
      templateResult: function (result) {
          
          return result.text;
      },
      templateSelection: function (selection) {
          
          if (selection != undefined) {
              UserInfo.setLedgerId({key:selection.id, value:selection.text});
              if (selection.ledgerType != undefined) {
                  UserInfo.setLedgerType(selection.ledgerType);
                  calculateLedgerService({key:selection.id, value:selection.text}, 
                  selection.ledgerType, new Intl.DateTimeFormat('en-GB').format(UserInfo.getLedgerFromDate()), 
                 new Intl.DateTimeFormat('en-GB').format(UserInfo.getLedgerToDate()));
              }
          }
          return selection.text;
      },
      minimumInputLength: 3
  })
}

function calculateLedgerService(ledgerId, ledgerType, finStartYear, finEndYear) {
  console.log("Came inside calculateLedgerService")
  // 展示数据的相关代码
} 

渲染部分

<select className="select2 form-control required ledger" 
  isSearchable={true} isMulti={false}
  components={{ DropdownIndicator }}
  value={UserInfo.getLedgerId()} required
>
</select>

问题根源

  1. Select2默认不会在重复选择已选项时触发变更逻辑,因为它判定选中值没有变化,不会执行templateSelection里的代码
  2. useEffect依赖props,每次props变化都会重新初始化Select2,容易导致事件绑定混乱,且没有清理旧实例的逻辑
  3. React组件状态和jQuery的DOM操作分离,直接依赖全局UserInfo管理选中状态,容易出现状态不同步

修复方案

1. 添加重复选择的事件监听

给Select2绑定select2:select事件,这个事件不管是不是重复选择都会触发,手动执行业务逻辑;

2. 添加Select2实例清理逻辑

在useEffect的清理函数中销毁Select2实例,避免重复初始化导致的问题;

3. 优化状态管理(可选)

用React本地状态维护选中值,和全局UserInfo同步,减少直接操作DOM的依赖。

修改后的代码

组件逻辑部分

useEffect(() => {
  setLedgerDates();
  searchLedgerNames();
  
  if (props?.location?.state) {
    // 原有设置数据的逻辑
  }

  // 清理函数:销毁Select2实例,防止重复初始化
  return () => {
    $('.ledger').select2('destroy');
  };
}, [props]);

function searchLedgerNames() {
  $('.ledger').select2({
    placeholder: "Select Ledger",
    multiple: false,
    width: '100%',
    tags: false,
    allowClear: true,
    ajax: {
      url: config.searchLedgerNames,
      type: 'GET',
      data: function (params) {
        return {
          'searchName': params.term,
          'token': UserInfo.getToken()
        };
      },
      processResults: function (data) {
        if (data.status == 1) {      
          return {
            results: $.map(data.ledgerMap, function (item) {
              return {
                text: item.ledgerName,
                id: item.supplierOrCustomerId,
                ledgerType: item.ledgerType
              }
            })
          };
        }
      }
    },
    templateResult: function (result) {
      return result.text;
    },
    templateSelection: function (selection) {
      if (selection) {
        updateLedgerSelection(selection);
      }
      return selection.text;
    },
    minimumInputLength: 3
  })
  // 绑定select事件,处理重复选择
  .on('select2:select', function (e) {
    updateLedgerSelection(e.params.data);
  });
}

// 抽离重复逻辑,避免代码冗余
function updateLedgerSelection(selection) {
  UserInfo.setLedgerId({key:selection.id, value:selection.text});
  if (selection.ledgerType) {
    UserInfo.setLedgerType(selection.ledgerType);
    calculateLedgerService(
      {key:selection.id, value:selection.text}, 
      selection.ledgerType, 
      new Intl.DateTimeFormat('en-GB').format(UserInfo.getLedgerFromDate()), 
      new Intl.DateTimeFormat('en-GB').format(UserInfo.getLedgerToDate())
    );
  }
}

function calculateLedgerService(ledgerId, ledgerType, finStartYear, finEndYear) {
  console.log("Came inside calculateLedgerService")
  // 展示数据的相关代码
}

渲染部分(可选优化)

// 组件内添加本地状态
const [selectedLedger, setSelectedLedger] = useState(UserInfo.getLedgerId());

// 同步本地状态和全局UserInfo
useEffect(() => {
  const currentLedger = UserInfo.getLedgerId();
  setSelectedLedger(currentLedger);
}, []);

// 渲染select组件
<select 
  className="select2 form-control required ledger" 
  required
>
</select>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:25:43