-
-
Notifications
You must be signed in to change notification settings - Fork 95
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
Reactive/Store-like primitive #4
Comments
FYI: Devtools doesn't use something like that. |
I think we should deeply wrap items so that we can for instance do const r = reactive({ count: 0 });
r.count.value++ and see stuff change, not entirely sure if it's possible but those are my two cents coming from the Vue-like syntax. |
@JoviDeCroock That's a great idea! I think it'd definitely be nice to have some sort of helper method that initializes object properties as Signals. I'm not sure how deep that should go. Do you know how Vue handles these cases? // Are both "foo" and "bar" signals now?
const r = reactive({ foo: { bar: 123 }}); // Are both "foo" and the inner elements in the array signals?
const r = reactive({ foo: [ { bar: 123 }, { bar: 444 } ]}); |
From the explanation I assume it would wrap all of them as individual signals, it's hard to tell in the CSB as they eagerly unwrap https://codesandbox.io/s/magical-swanson-3cpwb8?file=/src/App.vue |
Currently looking at valtio and the more I look at it, the more I like it. Originally, I was worried that having two kind of values (proxy + boxed |
Quick and dirty, but I repurposed the port of It doesn't seem entirely broken, but there seem to be a bunch of APIs missing that would be needed to implement this efficiently. |
I came here to recommend this and for anyone in the mean-time, I just published a package called preact-signal-store which is meant to do just this. I expose a I personally think this model would make sense in |
deepSingnal is helpfull |
is better, if you have three or four deep object |
@chenjiangui I feel like that's kind of more confusing. One of the rules of a In import { deepSignal } from "preact-signal-store";
const userStore = deepSignal({
name: {
first: "Thor",
last: "Odinson"
},
email: "[email protected]"
});
// TS error: Cannot assign to 'email' because it is a read-only property.
userStore.value.email = "[email protected]"; Notably, what would work is this, which would actually update the original userStore.value = { email: "[email protected]" }; |
I opened a PR #217 PoC which could allow a single signal to track multiple values rather than creating multiple signals per each property. The PR doesn't attempt to be the "Reactive/Store-like primitive" but rather a building block which could allow to do it. |
Another take at deep signals, based on Proxies. I'll refine it a bit (add tests, avoid wrapping unsupported elements and built-ins, etc) and publish an npm package so people can use it and report feedback. I made it work as similar as possible to plain JavaScript objects, not to signals, because for my use case that's preferable. But making it as similar as possible to signals (like @EthanStandel's library) is also possible. Plain JS objectsIt's using const App = () => {
return (
<div>
{/* Pass the signal down to JSX */}
<div>Name: {user.$name}</div>
{/* It works, but triggers a component rerender */}
<div>Email: {user.email}</div>
</div>
);
}; It writes to the signal when you update the plain object: user.name = "Jon"; Signal-like objectsFor primitives, it could always return the signal: const App = () => {
return (
<div>
{/* Pass the signal down to JSX */}
<div>Name: {user.name}</div>
{/* It works, but triggers a component rerender */}
<div>Email: {user.email.value}</div>
</div>
);
}; And it could force people to write to the signal using user.name.value = "Jon"; I guess the main differences with @EthanStandel's library, apart from the plain-JS-object API, are that it's using lazy initialization (it creates proxies and signals on the fly) and it supports adding properties on the fly. |
I'll throw in my library in here as well: preact-observables The goal here was to create transparent observable proxies for objects, arrays, It wraps another library i'm working on nu-observables. Which allows for creating deep proxied observables with any underlying signal implementation (preact-signals, solid, mobx, etc etc) It uses lazy initialization and permanently associates an observable object with its source, meaning if you create an observable from a plain object it will always return the same observable instance no matter how many times you do it. So observing existing giant objects with circular references works and in constant time. When mutating , Other notable features include being able to model signal state with classes, optimized Array.prototype methods compared to a naive proxy implementation as well as some interesting performance escape hatches (more details in readme) Big thanks to @luisherranz as I copied their idea of using $ to return the signal instead of the value. |
I've been trying to make I've tried a similar approach to the one you're using here, but it has problems when mutating a nested object (because TypeScript thinks the export type DeepSignal<T extends object> = {
[P in keyof T & string as `$${P}`]: T[P] extends object
? Signal<DeepSignal<T[P]>>
: Signal<T[P]>;
} & {
[P in keyof T]: T[P] extends object ? DeepSignal<T[P]> : T[P];
}; I've opened an issue in your repository not to hijack this one with our problems 🙂 |
@luisherranz fwiw the store I posted here shouldn't have that problem, as it doesn't change in interface of the input object. If there's enough interest I could polish and maintain that somewhat rough port 🤔 |
It took me a bit, but here is the deep signal package. It is based on proxies and uses the It's small (the goal is to keep it under 1Kb), has lazy initialization, and full TypeScript support. https://github.com/luisherranz/deepsignal I used the exact same structure and testing as this repo (actually, I started with a fork) to make it as familiar as possible. |
There's also signal-struct for comparison. |
Open question: Should conversion be deep or shallow?
Pros
Cons
Update with assign()-syntax
Pros
Cons
The text was updated successfully, but these errors were encountered: