Open ekiwi111 opened 2 years ago
This is similar to https://github.com/quarrant/mobx-persist-store/issues/41 and https://github.com/quarrant/mobx-persist-store/issues/55 where you are trying to save a Map Object with references to classes. So basically you are doing this:
JSON.stringify(new Map(['productId', new Product(appStore)]);
JSON.stringify
is trying to convert all the objects to JSON but Product
has a reference to ShopStore
and there is a circular dependency (Product > ShopStore > Product > ShopStore
etc.). Every time JSON.stringify
converts a Product
to JSON it finds ShopStore
and tries to convert that but then it finds more Product
in products
which is a property on ShopStore
and the cycle never ends.
It is very hard to persist classes and/or Map's because if they are converted to JSON, then how do you rehydrate JSON back to classes and Map's. You would have to give makePersistable
a custom storage
controller that knows to turn the JSON back to classes and finally within a Map.
As of right now there is not a perfect solution for what you are trying to do. Persisting simple objects and arrays is currently the easiest way because in the end you are working with JSON.
@codeBelt Thank you for your explanation. It's a problem with circular dependencies and architecture. If you want to resolve this just remove circular dependencies.
For example, if you want create relation between to classes you may do it with any primitive identifier
class Shop {
constructor(public readonly name: string) {}
}
class Product {
constructor(public readonly id: string, public readonly shopName: string) {}
}
const shops = new Map([["appStore", new Shop("appStore")]]);
const appStoreShop = shops.get("appStore")!;
const product_1 = new Product("1234", appStoreShop.name);
const product_2 = new Product("5678", appStoreShop.name);
const productShop = shops.get(product_1.shopName);
This example uses an architecture without circular dependencies. I hope it helps you =)
Is it possible to exclude a property at the class level from being persisted? e.g. makeAutoObservable(this, { rootStore: false });
as an example in 'mobx'.
It'd be great if there'd be a similar functionality in mobx-persist-store
, e.g. in Product
:
// something like
persistableConfig(this, {
exclude: ['appStore']
});
Nope, but I’ll think about it
Is there a way to perform a dynamic check on persistance? e.g. in isPersisting
?
isPersisting
checks only top-level objects, not each nested level. We didn’t do this kind of work because it may be a really hard work.
For example, if I have a nested array with nested objects there are each object has a nested array I need to loop each array to find which property I want to exclude before persisting…
Anyway, I think your case is a good example what we couldn’t do with this library, because it will lead to low performance.
I know an approach how do it better, but not in this library. I need to think about it moreeeee
@ekiwi111 I just did this:
export class AppStore implements AppStoreType {
constructor() {
makeAutoObservable(this)
makePersistable(this, {
name: 'AppStore',
properties: Object.keys(this).filter(item => item !== 'dataStore') as (keyof this)[]
})
}
...
}
But now I have the problem where some stores have other, smaller stores as properties, but those smaller stores also sometimes reference dataStore
which references many other things.
It would be awesome to have a global ignore array in configurePersistable
settings! Then we could just put our parent store names there and let it do its awesome thing.
I will try making them private, because I have read that makePersistable
does not pick up privates but I'm not sure that's actually a feature so I'd be very happy to read about the recommended way of doing this.
Even if making parent stores private should or does not help here, it's a good idea because they should never be accessed from anywhere else but inside the class where they were defined.
What's the preferred pattern to follow in the case of persisting a store with one to many relationship to its dependent domain objects?
E.g. example store
And its domain items:
In this example it'd throw the following error when persistence is triggered: