-
This is potentially a I'm hoping to use classes as basically a more succinct However, while just For example, isolating a repro just inside of it('pathList with literal', () => {
const proxyCache = new WeakMap();
const s1 = {
firstName: 'f',
get fullName() { return this.firstName.toUpperCase(); },
};
const a1 = new WeakMap();
const p1 = createProxy(s1, a1, proxyCache);
noop(p1.fullName);
expect(affectedToPathList(s1, a1)).toEqual([['fullName']]);
}); The it('pathList with class', () => {
const proxyCache = new WeakMap();
class Author {
firstName = 'f';
get fullName() { return this.firstName.toUpperCase(); }
}
const s1 = new Author();
const a1 = new WeakMap();
const p1 = createProxy(s1, a1, proxyCache);
noop(p1.fullName);
noop(p1.firstName);
expect(affectedToPathList(s1, a1)).toEqual([]);
}); Is this expected? Fwiw I expected this to break using classes in Maybe I should just trust the magic :-), but, dunno, I want to use heavily use classes with valtio, so just wanted to make sure there were not any gotchas. Thank you! |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
Yes, it's fine.
No, proxyWithComputed and classes are very different. But, in the following example, you compare object getters and class getters. They are mostly the same.
Yes, class getters are in prototype, so it's not accessed. So, it's expected.
Isn't the last expect like Hm, is it because not calling - const p1 = createProxy(s1, a1, proxyCache);
+ const ss1 = snapshot(s1);
+ const p1 = createProxy(ss1, a1, proxyCache);
You can use React Dev Tools to see "affected" in useSnapshot. If it has |
Beta Was this translation helpful? Give feedback.
-
Thank you for the quick reply!
Ah okay. I want to respectful of your time, so can you point to any docs/threads that explain the difference and pros/cons of each? Or also happy to get a tldr. Naively, just looking at the GameStep demo, it seemed like there were "class getters doing what computeds do", and "class setters mutating what actions would do".
Hm, no it really is Ah okay, I had to it('pathList with class', () => {
const proxyCache = new WeakMap();
class Author {
firstName = 'f';
get fullName() {
return this.firstName.toUpperCase();
}
}
const s1 = new Author();
markToTrack(s1);
const a1 = new WeakMap();
const p1 = createProxy(s1, a1, proxyCache);
noop(p1.fullName);
expect(affectedToPathList(s1, a1)).toEqual([["fullName"]]);
}); So, good, now it does record But, back in valtio, it still seems like valtio using Here is a ~long-ish example, and it's just a unit test, but if I put import { act, fireEvent, render } from "@testing-library/react";
import React from "react";
import { proxy, useSnapshot } from "valtio";
class Book {
title = "b1";
pages = 10;
get bigTitle() {
return this.title.toUpperCase();
}
}
class Author {
age = 40;
books = [new Book()];
get oldAge() {
return this.age * 2;
}
}
const state = proxy(new Author());
function TestComponent() {
const snap = useSnapshot(state);
function incrementAge() {
console.log("incrementAge");
state.age++;
}
function changeTitle() {
console.log("changeTitle");
state.books[0].title += ".";
}
return (
<div>
<div data-testid="age">{snap.age} {snap.oldAge}</div>
<div data-testid="bigTitle">{snap.books[0].bigTitle}</div>
<div data-testid="incrementAge" onClick={incrementAge} />
<div data-testid="changeTitle" onClick={changeTitle} />
</div>
);
}
describe("ValtioApp", () => {
it("doesn't render if computed doesn't change", async () => {
const r = await render(<TestComponent />);
await clickAndWait(r.getByTestId("incrementAge"));
await clickAndWait(r.getByTestId("changeTitle"));
});
});
async function clickAndWait(e: Element): Promise<void> {
await act(async () => {
fireEvent.click(e);
await new Promise(jest.requireActual("timers").setImmediate);
});
} |
Beta Was this translation helpful? Give feedback.
-
proxyWithComputed and derive create a real proxy. So from valtio point of view, it's identical to Object getters and class getters are just functions, so it's identical to the following: const state = proxy({ firstName: 'f' });
const Component = () => {
const snap = useSnapshot(state);
const fullName = snap.firstName.toUpperCase();
// ...
}; |
Beta Was this translation helpful? Give feedback.
-
Going to close this discussion out b/c I found what was tripping me up: It'd be interesting to poke at fixing someday, but for now it just tripped up my learning curve. I also included an FYI about the behavior in my 2nd docs PR. Thanks! |
Beta Was this translation helpful? Give feedback.
Going to close this discussion out b/c I found what was tripping me up:
#545 (comment)
It'd be interesting to poke at fixing someday, but for now it just tripped up my learning curve.
I also included an FYI about the behavior in my 2nd docs PR.
Thanks!