Open naturalethic opened 6 years ago
you can
Source:
const { observable, observe } = require("@nx-js/observer-util")
const o = observable({
foo: {
bar: {
baz: 1
}
}
})
const ob = observe(() => {
console.log(o)
})
o.foo.bar.baz = 2
o.foo.bar.baz = 3
Complete output:
{ foo: { bar: { baz: 1 } } }
Proxies are created on demand, so the above code would never work, since no proxies are created for foo, bar and baz. To do so, the library should have to walk the entirely tree and create a proxy for every object on it on registering the observable.
If you need that functionality, you can implement that yourself by doing exactly that: recursively walk the tree and observing every property.
Ok, just for background this was in the context of react-easy-state, using a third party widget that takes a tree of data, i needed the widget to update whenever any element of the tree updates. I ended up using a different means for this case. It does seem like observing an entire tree is out of scope for react-easy-state.
Thanks.
Hey, this should work, I will check it in a sec.
Sooo, this lib (and easy state) intercepts everything that 'can be intercepted'. Built-in functions in JS are sometimes implemented in none JS code (C++ for example). The above console.log
statement is one of these cases, it recursively fetches the object keys in none JS code, which Proxies can not intercept. Consequently, the lib does not register the set of observable keys.
You can try this code for example and it will work.
const { observable, observe } = require("@nx-js/observer-util")
const o = observable({
foo: {
bar: {
baz: 1
}
}
})
const ob = observe(() => {
console.log(JSON.stringify(o))
})
o.foo.bar.baz = 2
o.foo.bar.baz = 3
JSON.stringify
is accessing the keys in JS, so the lib can intercept the observable get operations. Sadly I can not give any guarantees about the behavior of built-in functions, their behavior with Proxies is not yet specified by the spec. Last time I checked observe(console.log)
was working in Node.
Anyway, people rarely want to observe built-in functions, they usually observe 'normal JS code', which works all the time.
I hope this helps. (Could you include a small repro of your easy-state issue?)
Your problem with easy-state was probably something very different.
I see you were passing a tree of data to a third party component and expected it to re-render when the data tree was mutated. In this case the issue was that the third part component was not a view
(observer
). It did not know that it should re-render when the data changes.
Your component was not using the data (it was not accessing parts of it), it just passed it on to the third party component. That component used the data, but it was not a view
.
This seems the be a pretty common use case, I will try to think about a good alternative for it by tomorrow.
Wait, nested objects aren't made observable? Why not?
From react-easy-state docs: Use nested properties, computed properties with getters/setters, dynamic properties, arrays, ES6 collections and prototypal inheritance
@matthew-dean
Wait, nested objects aren't made observable? Why not?
How did you come to this conclusion? Nested objects are made observable on demand.
Is there an example how to observe every property in nested object? It seems that you have to explicitly use proxy observable inside observe function (value cannot be passed to it).
BTW, some examples in this repo's README is wrong.
observe(() => console.log(person), { scheduler: ... });
That log only observes person
itself, not nested properties. Should be:
observe(() => console.log(JSON.stringify(person)), { scheduler: ... });
Or some kind of explicit access of person.name
and person.age
.
I would like to be able to observe for any change in a deep object.