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>
问题根源
- Select2默认不会在重复选择已选项时触发变更逻辑,因为它判定选中值没有变化,不会执行
templateSelection里的代码 useEffect依赖props,每次props变化都会重新初始化Select2,容易导致事件绑定混乱,且没有清理旧实例的逻辑- 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
相关产品推荐
相关产品推荐

