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
相关产品推荐
相关产品推荐

