platform
platform copied to clipboard
feat(signals): enhance `withComputed` to automatically add `computed`…
Example:
const CounterStore = signalStore(
withState({ count: 0 }),
withComputed(({ count }) => ({
doubleCount: () => count() * 2,
})),
);
- Updated withComputed to automatically wrap functions in computed signals.
- Added tests to verify automatic computation and mixing user-defined computeds.
- Improved documentation to clarify the factory function's return type.
PR Checklist
Please check if your PR fulfills the following requirements:
- [x] The commit message follows our guidelines: https://github.com/ngrx/platform/blob/main/CONTRIBUTING.md#commit
- [x] Tests for the changes have been added (for bug fixes / features)
- [x] Documentation has been added / updated (for bug fixes / features)
PR Type
What kind of change does this PR introduce?
[ ] Bugfix
[x] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:
What is the current behavior?
Closes #4782
Does this PR introduce a breaking change?
[ ] Yes
[x] No
Deploy Preview for ngrx-io failed.
Built without sensitive environment variables
| Name | Link |
|---|---|
| Latest commit | 370a4744d3033d24cbf5430706114af15e6a7085 |
| Latest deploy log | https://app.netlify.com/projects/ngrx-io/deploys/685daeefe41b6000082c3c3e |
Deploy Preview for ngrx-site-v19 ready!
| Name | Link |
|---|---|
| Latest commit | 370a4744d3033d24cbf5430706114af15e6a7085 |
| Latest deploy log | https://app.netlify.com/projects/ngrx-site-v19/deploys/685daeef0dcd410008237be2 |
| Deploy Preview | https://deploy-preview-4822--ngrx-site-v19.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify project configuration.
@markostanimirovic, @timdeschryver.
I've applied the suggested changes with the following additions:
ComputedResultcalls its type now alsoComputedRecordinsteadComputedInput.- @markostanimirovic, you were suggesting
[P in keyof ComputedDictionary]: ComputedDictionary[P] extends Signal<any>; I used[P in keyof ComputedDictionary]: ComputedDictionary[P] extends Signal<unknown>. Is there a reason whyanyshould be preferred overunkown. - Type tests have been added to verify that we stick to the
Signaltype when that one is provided.
As discussed, the latest commit enables access to methods within withComputed. This is a necessary step toward supporting a potential withResource feature in the 20.x release line.
When a resource is in an error state, accessing its value will throw. Therefore, users must first verify the presence of a value using the hasValue method.
In the meantime, I am going to prepare the updated docs (in a separate PR).
Since this is a significant change, I've also asked @timdeschryver for a re-review.
const Store = signalStore(
withResource(() =>
// spreads members of the resource to the store, including hasValue as method
resource({
loader: () => Promise.resolve({ firstName: 'John', lastName: 'Doe' }),
})
),
withComputed((store) => ({
safeUser: () =>
store.user.hasValue()
? store.user.value()
: { firstName: '', lastName: '' },
}))
);
I'd very much like to have the ability to provide a function with a parameter that returns a signal in order to create an equivalent of a factory selector in ngrx store world. I know this can be achieved in the withMethod block but wouldn't it make sense to be able to do that from withComputed when it just all comes down to dealing with signals and not just observables etc?
Just asking because of this comment which would I assume make that hard:
Updated withComputed to automatically wrap functions in computed signals
But maybe the recommendation is to just use withMethod for that?
@maxime1992
I'd very much like to have the ability to provide a function with a parameter that returns a signal in order to create an equivalent of a factory selector in ngrx store world.
Yes, factory functions for computed are actually methods. So they should go in withMethods. The computed itself is of course also a function in technical terms, but I hope you see the difference in a function creating a computed vs. a function which is wrapped by a computed