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,而非整个对象:
- 修改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, {}), })
- 实现收藏/取消收藏的动作,以及获取收藏列表的视图:
.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
相关产品推荐
相关产品推荐

