为了避免不一致的传入数据,我在我的模型中添加了默认值。例如
const collectionModel = types.model({
type: types.optional(types.literal('collections'), 'collections'),
preview: types.optional(
types.model({
products: types.array(SelectableProduct)
}),
{}
),
data: types.optional(types.model({
items: 24,
perRow: 4,
global: types.optional(EvergreenQuery, {}),
curated: types.array(EvergreenItemSettings)
}), {})
})
这将允许我collectionModel
从一个空对象创建一个实例
collection1 = collectionModel.create({})
当您使用参考时,请确保使用safeReference
From the docs
* `types.safeReference` - A safe reference is like a standard reference, except that it accepts the undefined value by default
* and automatically sets itself to undefined (when the parent is a model) / removes itself from arrays and maps
* when the reference it is pointing to gets detached/destroyed.
*
* Strictly speaking it is a `types.maybe(types.reference(X))` with a customized `onInvalidate` option.
因此,如果您要删除存储中其他地方引用的节点,则该引用将设置为未定义。根据我的经验,损坏的引用特别难以调试。
我喜欢 mobx-state-tree 强迫我有一个明确的结构。这让我在编写逻辑之前想到了结构,以后简化了逻辑的编写。
一个哈克解决方案
您可以做的一个技巧是在保存快照之前实例化一个新模型。如果成功则保存快照,如果不成功则跳过它。
const MyModel = types.model({})
onSnapshot(myModelInstance, s => {
try {
const testModel = MyModel.create(s)
if (localStorage) {
// here you can save the snapshot because you know for sure it won't break
localStorage.setItem('snap', JSON.stringify(s))
}
} catch(e) {
// log or something
// OR
console.log(
'snapshot failed because of',
difference(s, JSON.parse(localStorage.getItem('snap'))
)
}
})
// this methos does a deep difference between two objects
export const difference = <T>(orObject: object, orBase: object): T => {
function changes(object: any, base: any): any {
return _.transform(object, function(
result: any,
value: any,
key: any
): any {
if (!_.isEqual(value, base[key])) {
result[key] =
_.isObject(value) && _.isObject(base[key])
? changes(value, base[key])
: value;
}
});
}
return changes(orObject, orBase);
};
diff 方法非常有用,因为它可以更容易地找出崩溃的原因。这样,localStorage 将只有有效的快照,任何无效的快照都会记录问题的原因。