在以下模型中,通过Error: [mobx-state-tree] A node cannot exists twice in the state tree. Failed to add SearchModel@/results/0 to path '/selectedItem'
动作将值分配给selectedItem
时,出现错误消息setSelectedItem
。我已经检查了文档,但不确定是什么引起了此问题。
感谢任何帮助。谢谢!
const SearchModel = types
.model({
results: types.array(ItemModel, []),
selectedItem:types.maybeNull(ItemModel,{ id: 0 })
})
.actions(self => ({
setSelectedItem(selItem) {
console.log( 'typeof(selItem)', typeof(selItem));
self.selectedItem=selItem;
}
}));
export default SearchModel;
答案 0 :(得分:1)
对于以后寻求解决此类错误的任何人,我使用了散布运算符将selItem
的浅表副本分配给self.selectedItem
,问题就消失了。
代码必须如下所示:
const SearchModel = types
.model({
results: types.array(ItemModel, []),
selectedItem:types.maybeNull(ItemModel,{ id: 0 })
})
.actions(self => ({
setSelectedItem(selItem) {
self.selectedItem = { ...selItem };
}
}));
export default SearchModel;
答案 1 :(得分:1)
另一种解决方案是使用Lodash库中的_.deepCopy。它比散布运算符更具通用性,因为它将递归遍历整棵树,而不是一棵树。这对于较大的树很有用,因此您不必传播两倍或三倍或四倍的传播,并且代码难以阅读。
这就是您如何在简单的mobx-state-tree存储中使用它的方法。它非常优雅,易于使用。
请注意:这是递归复制传递功能,因此如果对象太大,性能可能会很差。
import _ from 'lodash';
import { types, getRoot, destroy, flow } from "mobx-state-tree";
const SearchModel = types
.model({
results: types.array(ItemModel, []),
selectedItem:types.maybeNull(ItemModel,{ id: 0 })
})
.actions(self => ({
setSelectedItem(selItem) {
self.selectedItem = _.deepCopy(selItem);
}
}));
export default SearchModel;
答案 2 :(得分:0)
一种更好的可能性:使用mobx-state-tree applySnapshot函数。这样可以自动协调数据结构,并保留前进/后退功能,因此您可以在状态树中使用撤消/重做功能。
import { types, getRoot, destroy, flow, applySnapshot } from "mobx-state-tree";
const SearchModel = types
.model({
results: types.array(ItemModel, []),
selectedItem:types.maybeNull(ItemModel,{ id: 0 })
})
.actions(self => ({
setSelectedItem(selItem) {
applySnapshot(self.selectedItem, selItem);
}
}));
export default SearchModel;
答案 3 :(得分:0)
在我的情况下,我在级别2上有一个嵌套对象“地址”,因此我还需要为其指定修复程序:
setSelectedItem(selItem) {
let item = { ...selItem };
item.address = { ...selItem.address }
self.selectedItem = item;
}
答案 4 :(得分:0)
我在我们的 React TypeScript 中也遇到了同样的问题,而且我们的 MST 存储 非常嵌套并且复杂,因此使用扩展运算符或 applySnapshot 不起作用。通过使用 lodash 简单地解决了这个问题。
步骤:
安装: npm i lodash.clonedeep
导入: import cloneDeep from 'lodash/cloneDeep'
使用它(就我而言): self.filteredCashGamesList.cashGameTableView = cloneDeep(self.cashGameTableView)