Apollo不可变性错误:已做对象拷贝仍出现无法赋值只读属性问题
问题分析与解决
核心问题
你遇到的错误本质是直接修改了不可变对象的属性,虽然做了数组的浅拷贝,但存在两个关键问题:
- 变量名笔误:代码里定义了
updatedEmployees = [...employees],但后续使用的是updatedUnits,这是未定义的变量,逻辑本身就有问题。 - 浅拷贝的局限性:
[...employees]只是复制了数组的外层结构,数组内的每个unit对象仍然是原引用。如果原对象来自Apollo缓存或React状态(这类对象通常被冻结为只读),直接修改unit.status就会触发"Cannot assign to read only property"错误。
另外,Apollo Client返回的缓存对象默认是不可变的,employeeUpdateById本身可能也是只读的,直接操作其属性也会有风险。
修正代码
正确的做法是通过创建新对象的方式更新,完全遵循不可变性原则:
const [releaseHold] = useMutation(UPDATE_EMPLOYEE_STATUS, { update(cache, { data: { employeeUpdateById } }) { setLoading(false) handleClose() // 遍历数组,仅对目标对象创建副本并更新属性 const updatedEmployees = employees.map(unit => { if (unit._id === employeeUpdateById._id) { // 合并原对象属性与新状态,返回新对象 return { ...unit, status: employeeUpdateById.status } } // 非目标对象直接返回原引用 return unit }) setUnits(updatedEmployees) } })
为什么这样能解决问题
- 使用
map遍历数组,找到匹配的对象时返回全新的对象副本,而不是修改原对象,彻底避免了对只读对象的直接操作。 - 不需要单独拷贝整个数组再修改,
map本身会返回新数组,同时保证非目标对象的引用不变,兼顾性能和不可变性。
内容的提问来源于stack exchange,提问作者beNerd
相关产品推荐
相关产品推荐

