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

React.js与Mobx中查找集合元素时出现「TypeError: cyclic object value」错误的排查求助

解决Mobx集合查找时的「TypeError: cyclic object value」错误

这个错误看起来有点迷惑——明明功能正常,错误还指向CSS文件,但其实罪魁祸首是React DevTools在序列化Mobx Observable对象时遇到了循环引用,和你的CSS代码完全无关(webpack打包后混淆了文件名才显示成_product.css)。

问题原因

你在组件里用useState存储了Mobx返回的Observable对象:

setProduct(store.findById(+id))

Mobx 6的makeAutoObservable会给数组和对象添加内部的Observable元数据(比如$mobx属性),这些元数据里包含循环引用的结构。当React DevTools试图读取组件的state并序列化为JSON时,就会触发「cyclic object value」错误。

解决方案

有几个简单的修复方式,按推荐程度排序:

1. 直接使用Mobx状态,抛弃useState(最优解)

因为你已经用了observer包裹组件,Mobx会自动追踪状态变化并触发组件重渲染,完全不需要把Mobx的状态转成React的local state。修改组件代码:

const ProductDetail = () => {
  const { id } = useParams()
  // 直接通过store获取,不用useState
  const product = store.findById(+id)

  // 处理product为undefined的情况(比如id不存在)
  if (!product) return <div>Product not found</div>

  const { price, image } = product

  return (
    <section className="product-detail">
      <div> Product Page: {id} </div>
      <div>Price: {price}</div>
      <div>Image: {image}</div>
    </section>
  )
}

这样既简化了代码,又彻底避免了循环引用的问题。

2. 将Observable对象转为普通JS对象(如果一定要用useState)

如果因为某些原因必须使用local state,用Mobx提供的toJS方法把Observable对象转成普通对象(比JSON.parse(JSON.stringify())更可靠,能保留正确的类型):
首先导入toJS:

import { toJS } from "mobx"

然后修改useEffect:

useEffect(() => {
  const foundProduct = store.findById(+id)
  setProduct(foundProduct ? toJS(foundProduct) : {})
}, [id])

toJS会剥离Mobx的Observable元数据,得到一个干净的普通对象,DevTools序列化时就不会报错了。

3. 检查React DevTools版本

如果以上方法都没用,可能是你的React DevTools版本和Mobx 6不兼容。尝试更新浏览器的React DevTools扩展,或者暂时禁用DevTools的某些状态检查功能(不推荐,但可以临时排查问题)。

验证

修改后刷新页面,功能依然正常,控制台的「cyclic object value」错误应该会消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:19:06