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

Mobx-State-Tree报错:无法将模型数据从newsFeed复制到favorite

解决MobX-State-Tree对象重复加入状态树的错误

错误原因

MobX-State-Tree(MST)的核心约束是每个状态节点对象只能归属一个状态树分支。你直接将newsFeed数组中的News对象push到favorite数组时,该对象已经属于/newsStore/newsFeed/0这个状态分支,无法同时被添加到/newsStore/favorite/0,因此触发报错。

解决方案

方案1:创建独立的新节点(收藏与原数据独立)

通过获取原对象的快照,再基于快照创建一个全新的News节点,这样新节点不属于原状态分支,可以安全加入favorite数组:

.actions(self => ({
  setFav(item: NewsTypes) {
    // 获取原新闻对象的快照数据
    const itemSnapshot = types.snapshot(item);
    // 用快照创建新的News节点并加入收藏数组
    self.favorite.push(types.create(News, itemSnapshot));
  },
}))

方案2:存储ID引用(收藏与原数据同步)

如果希望收藏的新闻和原新闻保持数据同步(比如原新闻更新后收藏列表也同步变化),可以改为存储新闻的唯一ID,而非整个对象:

  1. 修改NewsModel的props定义:
export const NewsModel = types
  .model('News')
  .props({
    newsFeed: types.array(News),
    // 将favorite改为存储新闻ID的数组
    favoriteIds: types.array(types.string),
    totalResults: types.maybeNull(types.number),
    newsUserTask: types.optional(AsyncTask, {}),
  })
  1. 实现收藏/取消收藏的动作,以及获取收藏列表的视图:
.actions(self => ({
  setFav(item: NewsTypes) {
    // 避免重复添加同一新闻
    if (!self.favoriteIds.includes(item.id)) {
      self.favoriteIds.push(item.id);
    }
  },
  removeFav(itemId: string) {
    self.favoriteIds = self.favoriteIds.filter(id => id !== itemId);
  }
}))
// 添加视图属性,通过ID过滤出收藏的新闻
.views(self => ({
  get favorite() {
    return self.newsFeed.filter(news => self.favoriteIds.includes(news.id));
  }
}))

额外优化:修复newsCall中的重复赋值问题

你的newsCall方法里存在重复的self.newsFeed赋值逻辑,会导致数据重复加载,建议删除外层的重复赋值代码:

// 原代码中if分支后重复的这行要删除
// self.newsFeed = castToSnapshot([
//   ...self.newsFeed,
//   ...(result as NewsTypeResponse).articles,
// ]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 11:16:04