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

Apollo不可变性错误:已做对象拷贝仍出现无法赋值只读属性问题

问题分析与解决

核心问题

你遇到的错误本质是直接修改了不可变对象的属性,虽然做了数组的浅拷贝,但存在两个关键问题:

  1. 变量名笔误:代码里定义了updatedEmployees = [...employees],但后续使用的是updatedUnits,这是未定义的变量,逻辑本身就有问题。
  2. 浅拷贝的局限性:[...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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:05:07