Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shallow observing #53

Open
k1w1 opened this issue Nov 11, 2021 · 1 comment
Open

Shallow observing #53

k1w1 opened this issue Nov 11, 2021 · 1 comment

Comments

@k1w1
Copy link

k1w1 commented Nov 11, 2021

I came across a problem using react-easy-state that feels like a limitation in observer-util.

To make sure that React re-renders when an object assignment changes, the object needs to be observed. But observing properties inside the object can have negative effects. Observing the object "pollutes" everything inside it by wrapping properties in proxies and propagating the proxies deeper and deeper into the hierarchy of nested objects as the object mutates over time.

Imagine the object comes from an unrelated Javascript library and cannot tolerate the performance impact of proxy observers on every nested property or object. In addition adding proxies prevents object equality checks from working when a proxied version of the object is compared with a non-proxied version. Again, because this is in a third-party library it is not possible to use raw to fix the equality.

It seems like the only solution would be to have a kind of "shallow" observer that only observes the object itself (or perhaps the container of the object), and none of the object's properties. It is not completely clear to me how this could work in a way that was not too burdensome on the programmer. I am wondering if you have thought about this problem before and have any ideas for solutions.

@k1w1
Copy link
Author

k1w1 commented Nov 11, 2021

Here is a jsfiddle that demonstrates the desired behavior.

import { observable, observe } from 'https://unpkg.com/@nx-js/observer-util@4.2.2/dist/es.es6.js';

const obj1 = {
  name: "My complex object",
  subObj: { val: 1 },
}
const obj2= {
  name: "Second complex object",
  subObj: { val: 2 },
}
const state = observable({
  currentObject: null,
});

observe(() => console.log(`${state.currentObject?.name}`));

console.log("Start observing:")

// Should log
state.currentObject = obj1;

// Should log
state.currentObject = obj2;

// Should not log - we only want to observe changes to state.currentObject, but not changes inside state.currentObject.
state.currentObject.name = 'Very complex object';

I imagine an API like:

// Don't observe changes inside `obj1`
state.currentObject = notObservable(obj1);

that does not observe inside obj1.

A trivial implementation would be to have notObservable add a new property to the object, like __DONT_OBSERVE and then in observable(), ignore objects with that property. In the same way that shouldInstrument is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant