Comments (7)
Cool, what was the result of this consideration?
Btw, if it is introduced later on in the library with the name deepComputed
, wouldn't it make sense to rename signalState
to deepSignal
? Maybe it's just me, but I find the name deepSignal
more descriptive than signalState
. I myself created a wrapper around signalState so that it's called deepSignal when I use it haha.
from platform.
Unless I'm mistaken on your request, then is what the signalState
function does.
https://ngrx.io/guide/signals/signal-state
We wouldn't created a computed
function that does what signalState
does, as it might be confusing.
from platform.
No, signalState
creates a "deep" signal typed as SignalState
.
What I would like to have is the ability to get a computed deep signal.
For signals we have:
count = signal(0)
doubleCount = computed(() => {
return this.count() * 2
})
I would like the same but for deep signals, so something like:
count = signal(0)
doubleCount = computedState(() => {
return this.count() * 2
})
Hence, doubleCount
would be a SignalState
instead of a Signal
.
For primitives, this isn't very useful. But this would be useful for non-primitive values.
Examples with non-primitive values:
- Signal based approach
profile = signalState({
firstName: "Georges",
lastName: "Bob",
})
computedSignal = computed(() => {
return {
firstName: this.profile.firstName(),
lastName: "Alice"
}
})
- SignalState approach
profile = signalState({
firstName: "Georges",
lastName: "Bob",
})
computedSignalState = computedState(() => {
return {
firstName: this.profile.firstName(),
lastName: "Alice"
}
})
Do not really pay attention to the body of the computed()
and computedState()
functions, this is just to give you a quick example.
from platform.
Right know, you can only have signals when using computed()
, which give you this when using it:
<p>
{{ computedSignal().firstName }}
</p>
Whereas with a deep signal that you could get with computedState()
, you could do:
<p>
{{ computedSignalState.firstName() }}
</p>
Which is better for template rendering/change detection. With the computedSignalState
solution, change detection would only be triggered if firstName
has changed. Whereas, with the computedSignal
solution, change detection is triggered every time computedSignal is updated, even if firstName hasn't changed.
from platform.
We already considered this feature some time ago - deepComputed
:
const counts = signalState({ count1: 1, count2: 2 });
const doubleCounts = deepComputed(() => ({
count1: counts.count1() * 2,
count2: counts.count2() * 2,
});
console.log(doubleCounts()); // { count1: 2, count2: 4 }
console.log(doubleCounts.count1()); // 2
console.log(doubleCounts.count2()); // 4
from platform.
@JulienLecoq I get the idea that the API is different and you like it more, but I'm not sure what problem are you trying to solve here. Since computeds are cached anyway, don't think perf could make much difference here.
Especially in this section:
Describe any alternatives/workarounds you're currently using
I'm using the computed() function provided by Angular which returns a Signal.
In what way would the proposed deepComputed
be better?
IMO the fact that e.g. the store itself is NOT a signal, or that we've got DeepSignals, etc. - all these are implementation details. The wonderful thing in the signal store design is its simplicity. By exposing additional withDeepComputed
(or whatever) the complexity gets higher. It appears as an abstraction leak to me.
Currently the fact that signalStore
creates deep signals is hidden behind a proxy. And thanks to precise typing, you can easily use those deep signals without even knowing how all those things work. You can't decide directly whether a piece in signal store is a DeepSignal vs Signal (correct me @markostanimirovic if I'm mistaken). IMO encapsulating computed vs DeepComputed makes a better approach - as it doesn't leak abstraction.
from platform.
@ducin
Here is a scenario where withDeepComputed
would be useful:
I have a RecipeStore
which is a SignalStore
as the root store.
Then I also have a withControlPoints()
function to get a signalStoreFeature()
and that adds to the root state an attribute controlPoints
. But if you look at the RecipeStore attributes from their initial state, they are all DeepSignals
, while the attributes derived from the computed signalStoreFeatured
are regular signals.
In the end, when we access the store from a component, we see all the attributes, but some of them are deepSignals
(from the initial state) while others are regular Signals (from computed). This is confusing.
The ideal would be to return DeepSignals when using withComputed()
by default.
Edit:
When accessing a store from a component or service, I would expect to have all the attributes as DeepSignals
, not only the ones created on the initialState.
from platform.
Related Issues (20)
- untracked for all methods? HOT 4
- @ngrx/signals: ability to save entity class instance on updateEntity() HOT 1
- Expose more models to the public API: SignalStoreFeatureResult and InputSignalStore<Input>
- Using a custom generic function for defining props in createActionGroup results in weird TypeScript errors HOT 4
- Chaining custom signal store features with input declared as functions fails HOT 2
- @ngrx/effects/src/effect_creator.d.ts:12:43 - error TS2313: Type parameter 'OT' has a circular constraint. HOT 17
- Schematics 'feature' gives error "Property 'entity' does not match the schema. 'false' should be a 'boolean'." HOT 8
- `patchState` TypeScript v5.4 compilation error HOT 3
- updater-explicit-return-type No longer needed with NoInfer HOT 2
- Cannot generate feature inside module with schematics HOT 2
- RFC: Allow constructor injection of SignalStore
- RFC: SignalStore with WritableSignals and ReadOnlySignalStore HOT 8
- Signal Store with Angular SSR initiate store in every injected component HOT 2
- Type 'Unsubscribable' must have a '[Symbol.iterator]()' method that returns an iterator. HOT 2
- Return type of selectQueryParam is incorrect HOT 2
- SignalStore Methods code snipped has probably a flaw HOT 4
- eslint plugin should use correct version of 'concatLatestFrom' in autofix for rule 'prefer-concat-latest-from' HOT 5
- Provide properly typed selectors example for CustomSerializer
- No usage notes for `tapResponse`, `concatLatestFrom` operators. HOT 1
- Ngrx dependency injection issue with esbuild/build-angular:application HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from platform.