Bulk computed / Observing proxy / Observing result of Object.create ? #3276
-
I have a Store with large number of computed properties. They derive from data made up of defaults and, usually, a few user modifications. But it is possible for any data prop to be modified by a user. Think a large group of settings. Because the user overrides are almost always way smaller than the data, I'd like to efficiently serialize the store by saving only the user modifications, i.e. I'd like the store properties to derive from data that is itself a function of the defaults and user changes. Sans MobX, structuring the data as desired might be done via Object.create or a proxy, but neither of the produced entities seem to become easily observable. Rough example w/ Object.create const defaults = {p:1,...}
let userData = Object.create(defaults)
// ... later
JSON.stringify(userData) // produces just what was changed
// However, observing userData breaks the prototype link to defaults such that userData.p will return undefined unless explicitly set on userData. Rough example with Proxy let defaults = {p:1}
let userData = {} as Partial<typeof defaults>
let data = observable(new Proxy(defaults,{
get:(t,prop)=>{
// continues to work fine
return userData[prop] ?? defaults[prop]
},
set:(t,prop,val)=>{
// this trap is lost if data is made an observable
userData[prop] = val
return true
}
}))
data.p = 99
console.log(userData) // does not include p:99 Obviously this could be done in each computed, e.g. get myComputed(){ return someMath( this.userData.prop ?? this.defaults.prop) } But this becomes onerous with lots of computeds and splits a general relationship (the data is a function of settings and defaults) unto lots of little bits. The alternative to these seems to use Is that indeed the best route for a situation like this? Have I misunderstood something about observing proxies or the results of Object.create ? Perhaps there's another route with some kind of transform? Thought I'd raise the question given the situation – data as a function of defaults and overrides w/ a need for efficient serialization by just saving overrides – didn't seem super novel and also felt like something that would be right in line with what MobX would nail with ease. Cheers! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
There is a quirk in impl https://mobx.js.org/observable-state.html#limitations (point 14), can't be changed until next major.
I think it should be possible to do something like (did not test): const defaults = observable({}); // if immutable, observable is redundant
const userData = observable({});
const data = new Proxy(userData,{
get(t,prop,r) {
return Reflect.get(userData, prop, r) ?? Reflect.get(defaults, prop, r)
}
set(t,prop,val,r) {
return Reflect.set(userData, prop, val, r);
}
}) Other approaches to consider: Also note Also make sure to understand the difference: |
Beta Was this translation helpful? Give feedback.
-
Greatly appreciate the response! I did not realize that a proxy relationship like in your example would trigger reactions down the line! I admit I'm not 100% clear on the api alternative but I'll consider it more and come back if it becomes a real sticking point. Appreciate the alternative line of thinking regardless. Also updated my proxy example to be explicit with how it was being made an observable. |
Beta Was this translation helpful? Give feedback.
There is a quirk in impl https://mobx.js.org/observable-state.html#limitations (point 14), can't be changed until next major.
I think it should be possible to do something like (did not test):
Other approaches to consider:
Change the API so you don't need the setting keys to be represented as fields, but eg
get(Settings.EMAIL)
/set(Settings.E…