-
Notifications
You must be signed in to change notification settings - Fork 1
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
RFC: Angular SignalArray and SignalDict #1
Comments
I like the idea, especially having a Signal-based Array type. Instead of |
I think i like writing this code havn't tried so can't tell. But i feel we're just replacing all the methods we had in rxjs with signal ones, and if we like rxjs why not just use rxjs? I feel that signals are here to simplify the core of our reactive primitive. In extension to that there is a saying about programming languages: If the complexity is not in your language its in your code. I feel that applies to frontend frameworks as well (if the complexity is not in your framework its in your app). This is also an abstraction on what is underneath so as a developer i need yet a layer of interpretation for the mind to comprehend one more thing to learn, to onboard new devs. Anyway im not against you're efforts here i think it could bring value i just think, it's worth having a thought about is this really an improvement. Much love! |
This is definitely nice. Is it worth it, tho ? 🤔 I'm not sure if |
thanks for all the comments so far! One thing to note that I forgot to mention in motivation (fixed already): for big data sets, having one signal can affect performance (changes on ingle items make the entire signal notify about a change). Creating a collection (array/dict) of manually maintained smaller signals introduces boilerplate. This is where collection signals kick in. @manfredsteyer 👌 makes sense @sp90 I definitely get your point and agree! The thing is - there's no reactive primitive in the language (JS), so if the framework brings a new reactive primitive (signal) but doesn't cover the most important APIs (Object, Array) then people would have to wrap them over and over and over again. And that's my point here.
💯 !
sure. But there are already redundant things in the framework (as directives vs component composition, pipes vs just service methods, or even NgModules which are being completely withdrawn from) which are completely redundant, yet, some people find them useful anyway. Let's look at what we have now (no array signal, no dict signal etc.): one has to learn array/object API and one needs to learn signals and one needs to track whether something is a static value (number, object etc) or a reactive value (number signal, object signal etc.). Your respomnsibility (now) is to do the mapping everywhere. The point of this RFC to automate the non-reactive-to-reactive. @GabrielBB yeah, that's THE RIGHT question :) what would you prefer:
|
This proposal is great and would significantly enhance the signal DX.
|
This looks great! I was thinking on solutions to the same problem you describe for a project of my own, happy to see work on a powerful solution like the one you propose. Some thoughts:
Again, thanks so much for this well rounded RFC! |
While I would welcome a Signal array, I would go in the opposite direction :
Those 3 methods would make the signal as dirty. What I don't grasp is why you would add all those methods that are already available on arrays. Also note: Methods are not removed by tree shaking, so the less we have the better. |
I'm pretty interested in these kinds of explorations! I think the
This decouples mutations of individual items from structural changes. The outer signal only fires (with a new array instance) when items are added or removed from the array itself. Because each item is a signal, the identity of items remains stable even when the values inside can be mutated.
Your This allows for updating an individual item without causing the whole array signal to recompute.
The main value of |
@alxhub I would argue that if an individual item is updated, any consumers of the array should be notified. Since change detection of computed relies on identity, that could only be achieved with immutability. As with anything, it will depend on the use case, but I feel that the behavior described in this RFC makes sense as a default. |
In some use cases, the array structure is watched but changes to the values themselves aren't relevant. One such use case is perhaps the most critical in the framework - repeating UI with At a high level, you can think of Diffing for changes is fast, but it's still an O(n) operation and not one we want to run frequently. Therefore, it's incredibly beneficial for The nice thing is that exposing the elements as separate signals has perfect behavior for when you do want to watch both the array and each item. For example, you could re-implement function every<T>(arr: ArraySignal<T>, predicate: (value: T) => boolean): boolean {
for (const value of arr()) {
if (!predicate(value()) {
return false;
}
}
return true;
} Using this function inside a reactive context (like a |
soooo.... do it? |
Yes, we need this badly |
👉 see full typescript playground for arrays
👉 see full typescript playground for objects
Motivation
SignalArray
s are meant to make arrays reactive. Native arrays, being mutable and non-reactive, require being wrapped withcomputed
calls e.g. to make them reactive in case of displaying in templates or re-running side effects.Wrapping an array calculation with
computed
is a simple task. However, in big scale it can become tedious and, as Angular will introduce signal/zoneless components, reactive arrays make a great fit. Knowing and, first and foremost, having to adjust mutable JS APIs into reactive Angular APIs is an implementation detail that shall not be developer's responsibility. Especially in Signal ComponentsFor big data sets, having one signal can affect performance (changes on ingle items make the entire signal notify about a change). Creating a collection (array/dict) of manually maintained smaller signals introduces boilerplate. This is where collection signals kick in.
Note that NGRX signal store does exactly this with its DeepSignals.
Scope
The scope of this RFC is the API design of native JS
Array
andObject
equivalents.Approach
key points:
SignalArray
Following interfaces illustrate a rather precise API proposal:
and following usage examples describe the characteristics:
1.
SignalArray
is a signal itself2. each item is a signal as well (slight performance improvement)
3. all methods return computed signals
4. all array-processing methods try to resemble Array API AMAP for convenience
5. mutations - NOT signals
modifying the
SignalArray
changes its state, never return a new signal (equivalent to signa.update)SignalDict
Following interfaces illustrate a rather precise API proposal. Note that - similar with static
Object
methods which useArray
methods - some ofSignalDict
methods useSignalArray
methods too:and usage
1. all object-processing methods try to resemble Object API
1.1 items
1.2 collection - chainable with SignalArray
2. mutations - NOT signals
modifying the SignalArray changes its state, never return a new signal
2.1 modifications
2.2 insertions
2.3 removals
The text was updated successfully, but these errors were encountered: