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

React setState使用点或括号表示法设置动态键名失败如何解决?

React动态设置state对象键名问题

问题描述

需要为动态数据集设置state,数据加载完成后在componentDidUpdate生命周期函数中遍历数据集,尝试根据每个元素的Id为其在state中设置对应状态。选择使用id而非索引,是因为数据渲染后索引无法被访问,无法用于定位元素。

尝试设置state时IDE抛出语法错误,提示点表示法或括号表示法不符合预期,原始代码如下:

componentDidUpdate(prevProps, prevState){
    if(this.props.report !== prevProps.report && this.props.report !== undefined){
      //set checkbox state dynamically for each row
      this.props.report.systemSourceList.forEach((item) =>
      this.setState((prevState) => ({selectedSourceRowIds : [...prevState.selectedSourceRowIds, {item['sourceId']: true}]}))
    }
}

先后尝试了item.sourceId和item['sourceId']两种写法均无法正常运行。将item.sourceId赋值给变量id后,控制台可以正常打印id的取值,但将该变量作为对象键名传入时,最终生成的对象键为固定字符串"id",而非id变量对应的实际值,对应代码如下:

this.props.report.systemSourceList.forEach((item) => {
        let id = item.sourceId;
        console.log(id);
         this.setState((prevState) => ({selectedSourceRowIds : [...prevState.selectedSourceRowIds, {id: true}]}))
      });
    }

遍历的对象结构如下:

{ 
systemId: 13, 
facilityId: 4747, 
sourceId: "WS010", 
}

错误原因

该问题由JavaScript对象字面量的语法规则导致:

  • ES6之前的标准中,对象字面量的键只能是固定字符串,书写{id: true}时,JS会直接将id识别为字符串类型的键名,不会读取对应变量的实际值
  • 直接书写{item['sourceId']: true}不符合原生JS语法规范,因此IDE会抛出语法错误

解决方案

使用ES6新增的计算属性名语法即可解决该问题,只需给动态键名外层包裹方括号,JS会先计算变量的实际值,再作为对象的键名使用,最终可运行的代码如下:

this.props.report.systemSourceList.forEach((item) => {
        let id = item.sourceId;
        console.log(id);
         this.setState((prevState) => ({selectedSourceRowIds : [...prevState.selectedSourceRowIds, {[id]: true}]}))
      });

优化方案

上述实现遍历数组时多次调用setState,每次调用都会触发组件更新逻辑,存在不必要的性能开销。可先批量处理好要新增的项,再一次性更新state,优化后代码如下:

componentDidUpdate(prevProps, prevState){
    // 可选链判断避免属性不存在时报错
    if(this.props.report !== prevProps.report && this.props.report?.systemSourceList){
      // 批量生成所有要新增的对象项
      const newSourceItems = this.props.report.systemSourceList.map(item => ({
        [item.sourceId]: true
      }))
      // 一次性更新state,仅触发一次重渲染
      this.setState(prevState => ({
        selectedSourceRowIds: [...prevState.selectedSourceRowIds, ...newSourceItems]
      }))
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:36:02