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

React中修改部门名称遇TypeError: "name" is read-only问题求助

问题原因分析

出现TypeError: "name" is read-only的核心原因是你只做了浅拷贝,修改的还是原数据的引用:

  • [...companies]仅复制了数组的外层结构,但数组内的公司对象、公司下的children数组、部门对象都和原数据共享引用。
  • 如果原数据里的部门对象是不可变的(比如被Object.freeze()冻结、来自Redux等不可变状态管理库、或是API返回后被标记为只读的数据),直接修改它的name属性就会触发只读限制。
解决方法

方法一:逐层手动深拷贝(无依赖推荐)

通过逐层复制对象和数组,确保修改的是完全独立的新对象,不会触碰原只读数据:

const handleDepartmentChange = (companyIndex, departmentIndex, e) => {
  const newCompanies = companies.map((company, idx) => {
    // 仅处理目标公司
    if (idx !== companyIndex) return company;
    // 复制当前公司对象,再处理其children数组
    return {
      ...company,
      children: company.children.map((dept, deptIdx) => {
        // 仅处理目标部门
        if (deptIdx !== departmentIndex) return dept;
        // 复制部门对象并修改name
        return { ...dept, name: e.target.value };
      })
    };
  });
  setCompanies(newCompanies);
};

方法二:使用深拷贝工具(适合复杂数据结构)

如果数据层级很深,手动拷贝太繁琐,可以用成熟的深拷贝工具(比如lodash的cloneDeep)一次性复制整个数据结构:

// 先安装lodash:npm install lodash
import cloneDeep from 'lodash/cloneDeep';

const handleDepartmentChange = (companyIndex, departmentIndex, e) => {
  const newCompanies = cloneDeep(companies);
  newCompanies[companyIndex].children[departmentIndex].name = e.target.value;
  setCompanies(newCompanies);
};

方法三:排查原数据的只读来源

检查companies数据的初始化逻辑:

  • 如果是用Object.freeze()冻结的,不要冻结需要修改的层级,或者在修改前先复制出可修改的副本。
  • 如果是从父组件props传入的不可变数据,不要直接修改,而是通过回调通知父组件更新状态。

内容的提问来源于stack exchange,提问作者Samathi kisalka Sapumana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:38:15