Like to get some feedback/thoughts about the following challenge.
I have been working on a two way binding library reaching completion and left with an enhancement and looking for the best approach moving forward.
I am tracking the properties of an object (e.g. state) with basic getters/setters. On changes routines are executed to update the DOM. Extremely simplified example:
var state = {propertyA:1,propertyB:2,propertyC:3}
state.forEach((prop) => {
Object.defineProperty(state, prop, {
set: function (newValue) {
value = newValue;
// routines to update the DOM based on the changed state
},
get: function () {
return value;
},
enumerable: true,
configurable: true
});
}
However runtime this state object might end up receiving new properties. I seek to remove the dependency of having to manually reinitialize all properties again.
So I need to track the state object and add the necessary setters/getters for the appended properties. I tried the following, but I am not allowed to touch the state object despite having set configurable to true.
Object.defineProperty(window, 'state', {
set: function (newValue) {
value = newValue;
// routine to apply setters/getters for the new properties
},
get: function () {
return value;
},
enumerable: true,
configurable: true
});
I really would like to avoid super nasty stuff like setInterval to check object changes. Any advice on how to handle this situation?
You can use a Proxyobject to do this simply.
For the MDN docs:
The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).
let state = {
propertyA: 1,
propertyB: 2,
propertyC: 3
}
function wrapObject(state) {
const handler = {
get: function(obj, prop) {
console.log("get invoked for prop:: ", prop);
return prop;
},
set: function(obj, prop, value) {
console.log("set invoked for prop:: ", prop, " and value:: ", value);
document.getElementById("root").innerHTML = `<div> prop: ${prop} value: ${value} </div>`;
//Other code
}
};
return new Proxy(state, handler);
}
state = wrapObject(state);
state.propertyA;
state.propertyD = 4;
//Update state by adding new property after 3 secs
setTimeout(() => {
state.propertyE = 5;
}, 3000);
<div id="root"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With