-
-
Notifications
You must be signed in to change notification settings - Fork 257
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
Frozen page when proxying an instance of EventEmitter #178
Comments
Line 117 in 51ccf16
EventEmitter wouldn't work even without snapshot. Line 158 in 51ccf16
|
Thanks for the explanation! Is there a chance to throw a more meaningful error in that case? |
It would be nice but pretty difficult. The meaningful message could only be made at creation. |
Do you know why |
No. What would happen if you do this? p = proxy(new EventEmitter())
p.on('Notification', fn) By serializable, I almost meant |
> new EventEmitter().domain
Domain {
_events: [Object: null prototype] {
removeListener: [Function: updateExceptionCapture],
newListener: [Function: updateExceptionCapture],
error: [Function: debugDomainError]
},
_eventsCount: 3,
_maxListeners: undefined,
members: [],
[Symbol(kCapture)]: false,
[Symbol(kWeak)]: WeakReference {}
} null prototype looks unusual. WeakReference is not properly excluded. Not sure if this is the fundamental reason. There could be so many of them. |
p = proxy(new EventEmitter())
p.on('Notification', fn) produce no error. |
The trigger is 93 | const getMutableSource = (proxyObject) => {
94 | if (!mutableSourceCache.has(proxyObject)) {
> 95 | mutableSourceCache.set(proxyObject, createMutableSource(proxyObject, getVersion));
96 | }
97 | return mutableSourceCache.get(proxyObject);
98 | }; |
This is pretty common to not inherit from the default |
Oh, so you don't have any issues unless you use
This means the
Yeah, maybe there's no issue on this. |
Yes |
Okay, so proxy-compare is the library used in useSnapshot for tracking state usage (= property access). However, in valtio, we found there's a good use case to define a state with class syntax. Line 91 in 51ccf16
However, this caused a problem when people put non plain objects like Line 96 in 51ccf16
And, these exceptions confused you... So, in summary, valtio supports plain objects and arrays, plus simple class syntax to produce plain objects, |
From the developer's perspective, this is highly confusing because I assumed that I can assign any js value. I'd added it to the README. |
Yeah, let's do that. |
Don't you think that splitting import { proxy } from 'valtio'
export const state = proxy({
count: 0,
name: 'foo',
})
export const actions = {
inc: () => {
++state.count
},
setName: (name) => {
state.name = name
},
} Disallowed (Only objects and arrays allowed) export const state = proxy({
count: 0,
name: 'foo',
inc() {
++this.count
},
setName(name) {
this.name = name
},
}) |
We accept both patterns: https://github.com/pmndrs/valtio/wiki/How-to-organize-actions So, "serializable-only" was a wrong conception.
I'd say plain objects (no custom prototype) or user-defined prototype (class syntax) are fine. |
Not sure if #180 is something you expected, but for now I would like to modify the section about |
Actually, I got a clear explanation on this. const state = proxy({
count: 0,
inc() {
++this.count;
}
});
console.log("before", state.count);
state.inc(); // this works fine
console.log("after", state.count);
const snap = snapshot(state);
console.log("before", snap.count);
snap.inc(); // this doesn't work because it's trying to mutate frozen snapshot
console.log("after", snap.count); https://codesandbox.io/s/adoring-lehmann-yji31?file=/src/App.js |
ok, this makes this way invalid https://github.com/pmndrs/valtio/wiki/How-to-organize-actions#using-class? |
https://github.com/pmndrs/valtio/wiki/How-to-organize-actions#action-methods-using-this is also using Both cases are valid as long as we use Both cases are invalid when we do |
I got it. The design is very hard to grasp. I'd expect an error like "Snapshot can't be modified, please use the state directly".
IMO this doesn't explain why eventEmitter doesn't work. |
My recommendation for beginners is no
That would be nice. At JS level, it would be hard. Maybe a good challenge for eslint-plugin-valtio.
I don't know, but it's the only the reason I can think why |
I wish I could get more feedback from anyone, but let me move forward. |
From #62 (comment)
The following code will result in:
Workaround
Avoid proxying
EventEmitter
withref()
I'd like to understand why it fails so badly. I'd assume that the proxy handles it transparently.
The text was updated successfully, but these errors were encountered: