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

React.js 复用可配置组件渲染多个Kendo ComboBox过滤器时数据错乱

问题诱因

1. 隐式全局变量污染(核心原因)

原代码在给filterDefinition、filterData赋值时,没有添加const/let声明关键字,浏览器会自动把这两个变量挂载到全局window对象上,所有6个DropDownFilterable组件共享同一个全局变量实例,这也完全匹配观察到的异常现象:

  • 同步渲染阶段:每个组件执行赋值操作后立刻渲染标题,读操作和赋值操作的时间差极短,所以每个过滤器的标题都能正确显示对应内容;
  • 异步请求阶段:所有接口的响应回调属于宏任务,会等所有同步渲染逻辑全部执行完才会触发,此时全局的filterDefinition已经被最后一个组件覆盖为自身的过滤器定义,所有请求拿到响应后都向同一个全局filterData写入值,最终最后一次写入的结果会被所有组件的ComboBox读取,就出现了“全部下拉框共用最后一个过滤器数据源”的问题。

2. 未使用React状态存储异步数据

即使修正了全局变量的问题,直接给普通变量赋值filterData = response也无法触发组件重渲染。React的界面更新完全依赖props、state的变化感知,普通JS变量的修改对React是无感知的,异步数据返回后ComboBox依然会保持初始空值,无法正常加载内容。

修正实现

按照以下逻辑调整代码,即可实现各下拉框加载对应配置数据源的预期效果:

  • 所有组件内部用到的变量必须在组件作用域内完成声明,杜绝隐式全局变量
  • 使用useState为每个组件实例单独维护自己的下拉数据源,保证组件间状态完全隔离
  • 接口响应返回后,调用setState方法更新当前组件的数据源,触发对应组件重渲染
  • 为useEffect补充正确的依赖项,保证每个组件仅在挂载时拉取一次对应ID的过滤器数据

修正后的核心组件代码参考:

const DropDownFilterable = (props) => {
  const appService = Service();
  // 从props获取当前组件专属的过滤器定义,仅在当前组件作用域内生效
  const filterDefinition = props.Definition;
  // 为每个组件单独初始化空的下拉数据源状态
  const [filterData, setFilterData] = React.useState([]);

  React.useEffect(() => {
    // 按当前组件的过滤器ID拉取对应数据源
    appService.getFilterValues(filterDefinition.Id).then(response => {
      // 更新当前组件的状态,不会影响其他同类型组件
      setFilterData(response);
    })
    // 依赖项设为当前过滤器ID,保证仅在ID变化时重新拉取数据
  }, [filterDefinition.Id]);

  return (
    <div>
      <div className="row" title={filterDefinition.DisplayName}>{filterDefinition.DisplayName}</div>
      <ComboBox 
          id={`filterComboBox_${filterDefinition.Id}`}
          data={filterData}
          style={{zIndex: 999999}}
          dataItemKey={filterDefinition?.Definition?.DataHeaders[0]}
          textField={filterDefinition?.Definition?.DataHeaders[1]}
        />
    </div>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 13:27:05