vanjs-org / van

🍦 VanJS: World's smallest reactive UI framework. Incredibly Powerful, Insanely Small - Everyone can build a useful UI app in an hour.
https://vanjs.org
MIT License
3.77k stars 87 forks source link

Error on when using method for Date data in VanX reactive (and possibly all class instance). #255

Closed mintong89 closed 7 months ago

mintong89 commented 7 months ago

When I create a reactive object with Date object in it:

const data = vanX.reactive({ date: new Date() })

If I calling a method from the date:

console.log(data.date.toString())

It gives error of:

TypeError: Method Date.prototype.toString called on incompatible receiver [object Date]

How can I solve it? Thanks!

LiquidAlmond commented 7 months ago

Here's a grain of salt to go along with my analysis since I'm a noob.

It appears reactive converts class instances to an object consisting of just the public variables of the class. The root issue can be replicated with the following.

class Test {
  #something;
  constructor(something) {
    this.#something = something;
  }
}
const test = new Test("something");
console.log(test.#something);
console.log(Object.entries(test));

// Check van.reactive({ test }) if you want

Conversing with ChatGPT has given a reasonable solution. We just need to change the !(srcObj instanceof Object) check in the reactive function to

!(srcObj && srcObj.contructor === Object && getPrototypeOf(srcObj))

We can make this smaller if we ignore the case where srcObj is created with Object.create(null). There may be other optimizations that I'm unaware of.

I believe this solution would make it so class instances are never reactive, which doesn't seem the greatest. There's probably another solution I'm missing.

LiquidAlmond commented 7 months ago

Well, my noobness was shining bright.

Seems the issue is more with how Date operates, specifically the value of this gets changed to the proxy instead of the Date object, which is what the functions in Date expect. Changing the get trap in the Proxy created in reactive to set the proper context on function calls might do the trick.

Tao-VanJS commented 7 months ago

See https://vanjs.org/x#caveat-native-reactivity.

mintong89 commented 7 months ago

ok got it, I guess I'll stringify the date before inserting into state. Thanks.