The same object being proxied has different references in scope of the same observable
When I assign the same const object as a value of the same observable - I get different reference every time:
store.reactiveField = constObject;
const cache = store.reactiveField;
store.reactiveField = constObject; // even tho we assign the same object, we got different reference
console.log(cache === store.reactiveField); // false
...I understand store.reactiveField and constObject are different objects (the first one is a proxy for the second one), but it still looks counterintuitive and error prone to get a new reference every time. For instance, when this proxy is used as a dependency for a react hook:
useEffect(() => {
// this effect is triggered every time I do `store.reactiveField = constObject`
}, [store.reactiveField]);Is it possible to preserve the reference in a case when the actual proxy target has the same reference?
If there is a reason for such behavior, is there any workaround for that? At the moment the only idea I have is to keep the copy of the original (non-proxied) value and perform deep assign manually:
// without safety checks for simplicity
function deepAssign(reactive, original, value) {
Object.entries(value).forEach(([ key, value ]) => {
if (original[key] !== value) {
reactive[key] = value;
return;
}
if (typeof value !== 'object') {
return;
}
deepAssign(reactive[key], original[key], value);
});
}Intended outcome:
I expect the same reference can be reused (since the underlying value has not changed):
console.log(cache === store.reactiveField); // trueActual outcome:
Reference is different every time:
console.log(cache === store.reactiveField); // falseHow to reproduce the issue:
Here is the example code to reproduce:
type TestObject = { number: number };
type Parent = { object: TestObject };
const object = { number: 0 };
const parent = { object };
class Store {
value: ParentObject = {}
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
store.value = parent;
const parentCache = store.value;
const objectCache = store.value.object;
store.value = parent;
console.log(parentCache === store.value); // false
console.log(objectCache === store.value.object); // falseVersions
^6.13.1
Source: mobxjs/mobx