I've really been enjoying the last few videos where you leverage these diagrams and a small snippet more than larger snippets. Yes they're more surface level, implementation wise, but they helping teach me the mindset you want to communicate.
"Avoid using effects for propagation of state changes." What about patching form with value from input signal, are there any declarative implementation for that scenario?
No, at least not out of the box. ReactiveForms are definitely awkward with signals, and for that matter they have always been awkward with observables as well anyway, but hopefully soon we see the Angular teams take on what forms become in a signal based world
I often myself using effect - most recently I used it to create a data source for a mat-table, using the input signal of the data, and the view child signal of the mat-sort. The mat-data-source is created with the data, and the mat-sort is assigned to it. Could I create a datasource in a computed? Quite possibly, but datasources seem to be wired more to receive updates directly to its properties rather than use signals to provide it data or sort.
I've use effects, twice, one for a third party library and another one to setup/remove event listeners on viewchildren based on a boolean signal input (even though I have found that with a mix of signal/rxjs and derivedAsync from ngxtension I could avoid the effect but I didn't want to rely too much on a third party library).
Did you consider trying Svelte 5 runes? It's literally signals, but with non-crazy syntax and without "going to monadland"; You use the language as you would use JavaScript normally (with normal read/assignment), and Svelte does it's magic with utmost efficiency without running any convoluted "changes checking" process, it just updates only what updated when they updated, cirurgically precise and efficient
I have like a carousel of components with text, basically at the top of the page hierarchy and i loop trough them. Each one has it's own state and they can "talk" to eachother, imagine sincronizing scroll between them (each one has its own scroll i mean). I'm new to angular and i'm still figuring it out how to update and mantain the state with just observables. If those components should be dumb and receive parameters or inject services.
Hard to know without working on the actual implementation, but you probably want your carousel items to be dumb components, and in terms of the topic of the video it is easier if we have state/data flowing in one direction (e.g. from the parent down). If you do need the items to affect state up stream then you would generally have the components emit an event that would be incorporated into the state of the parent, which technically you can do declaratively with viewChild and getting a reference to the event observable directly, or you might prefer to just "break reactivity" here and have the event callback next some subject/set some signal that is part of the carousel state.
Pretty much the one benefit you get with signals vs observables, is signals will trigger the change detection even in on push components. I have not really felt the need to move away from my existing ngrx (if the project uses it) or service hosted Behavior/Replay Subjects
My comment somehow dissapeared... So, how do you get something from external API using httpClient and set some signal as a result withou relying on some other library like NgRx or rxjs-interop? What exactly could go wrong if you subscribe to an observable inside an effect and set signal in subscription callback?
I wouldn't consider rxjs-interop another library since it is included in core, but as you're probably aware httpClient -> toSignal would be the most straightforward way out of the box. As for a signals only solution, Angular doesn't really have that yet, but hopefully we see something on that front soon. As for subscribing inside of an effect there are some dangers here in that a subscription is going to be created every time the effect runs, which not only has the potential for memory leaks if not carefully managed, but even if managed carefully it will still create race conditions, e.g. a signal the effect references updates again before the previous request has finished, so now you have two requests running on separate subscriptions racing to set a signal when they complete. On top of that, if it's something you care about, you lose the declarative connection where otherwise you could have your data source connected right through to where it is used in your application, but an effect/subscribe (instead of something like httpClient -> toSignal) loses that connection.
@@JoshuaMorony thank you for your reply, I agree with all of that, but... knowing it all, if you still decide to subscribe inside an effect and set some signal, is there anything else that could go wrong that causes angular team to be so loud about not updating the state inside an effect? Beside race condition (that could be mitigated), and breaking declarative approach (which is a personal decision in this case), I don't see any issues with that solution, as long as you're aware of what you're doing and you're doing that intentionally. Am I wrong?
@@mnemanja if you're already using RxJS anyway doing this inside an effect is just a more fragile/dangerous way to go about it, for the reasons mentioned its all downsides/no upsides. If your goal is to not use RxJS at all I think it makes a bit more sense as there isn't really a vanilla alternative right now. If you were to have an effect that uses the Fetch API to make a request/set a signal then I think it is more reasonable (especially if you don't care about declarative code). But you would still need to do some extra work if you want similar features to the RxJS approach (e.g. supplying a cleanup function to the effect that will trigger the AbortSignal for the fetch request)
@@JoshuaMorony Thanks, makes sense. The one issue I still have is that rxjs-interop is still marked as developer-preview. That makes me a bit anxious to implement it in a production system...
defensively not the case, try to make an Observable HTTP call and convert it to a signal using "toSignal" and without any subscribe you can freely use in template multiple times without worrying to subscribe or unsubscribe
@@ryzottyou do not need to unsubscribe from http client observables anyway. I used to always add on a pipe take 1 to http calls and then one day I found out http client subs auto unsub. I still add them to a subscription however and unsub the subscription OnDestroy. This is for if the component gets destroyed before the http call is finalized. You also probably shouldn't be using a http call in your template. Fn calls in templates bloat change detection iterations
Recently I run into a situation in which I didn't know how to avoid using an effect: I have a list with an scroll bar which the user can navigate with up or down kbd arrows. I created an effect that checks the focused item index and scrolls the list to that item using the scroll into view on the element reg native element. Any ideas how to do this without effects or in a declarative way?
You are using an event and to achieve reactivity with events is to use fromEvent operator it will listen to the event that in your case is scroll and the you can add further functionality and all that will be reactive
Thanks! The scroll is not the event, but the user pressing the down or up arrow keys, which I'm already listening to. These events change the state signal that contains the focused item index. I apply an effect on that signal to move the scroll bar to. So I think this is okish, since it's at the end of the reactivity stream, and there's no declarative way of doing this that I know of (maybe I could create a directive that scrolls to its element ref when it's focused..🤔)
effect is the same computed thing with restriction to write signals, so in order to continue reactivity you need to create another variable with computed
What do you think is missing? The "correct" path is deriving state rather than using effect/subscribe to create new state, and to generally only use effects for actual side effects that don't affect the state of the application
Joshua said about restart reactivity by doing it in subscribe, if you not intend to make anything to the end of the stream, then why use the tap operator ?
@@ryzott here’s the pattern I tend to use it in: someCmd$.pipe( withLatestFrom(state$), map((cmd, state) => { return a new state with the commands effect; }), tap((newState) => state$.next(newState)));
If you like the content, consider joining the newsletter: mobirony.ck.page/4a331b9076
I've really been enjoying the last few videos where you leverage these diagrams and a small snippet more than larger snippets. Yes they're more surface level, implementation wise, but they helping teach me the mindset you want to communicate.
Look ma, we're famous! 🤩 We agree, Alex is brilliant and we love him. He's an excellent teacher and so are you Joshua, thanks for the shout out! 🥰
"Avoid using effects for propagation of state changes." What about patching form with value from input signal, are there any declarative implementation for that scenario?
No, at least not out of the box. ReactiveForms are definitely awkward with signals, and for that matter they have always been awkward with observables as well anyway, but hopefully soon we see the Angular teams take on what forms become in a signal based world
Agreed forms with signals is driving me nuts!
It's great to know your views on the new angular signals model
Sooo its like and effect the video now?
I'm sad I didn't use this in the video
I feel like Angular just updated the docs, because the warnings for NOT using effects was not in there a few months ago. Maybe I'm crazy. 🤷♂
They’ve always been there afaik
yah its always there
I often myself using effect - most recently I used it to create a data source for a mat-table, using the input signal of the data, and the view child signal of the mat-sort. The mat-data-source is created with the data, and the mat-sort is assigned to it. Could I create a datasource in a computed? Quite possibly, but datasources seem to be wired more to receive updates directly to its properties rather than use signals to provide it data or sort.
I've use effects, twice, one for a third party library and another one to setup/remove event listeners on viewchildren based on a boolean signal input (even though I have found that with a mix of signal/rxjs and derivedAsync from ngxtension I could avoid the effect but I didn't want to rely too much on a third party library).
Did you consider trying Svelte 5 runes? It's literally signals, but with non-crazy syntax and without "going to monadland"; You use the language as you would use JavaScript normally (with normal read/assignment), and Svelte does it's magic with utmost efficiency without running any convoluted "changes checking" process, it just updates only what updated when they updated, cirurgically precise and efficient
No I haven't checked out runes yet, I do have a large Svelte project but it's on an older version at the moment
I have like a carousel of components with text, basically at the top of the page hierarchy and i loop trough them. Each one has it's own state and they can "talk" to eachother, imagine sincronizing scroll between them (each one has its own scroll i mean). I'm new to angular and i'm still figuring it out how to update and mantain the state with just observables. If those components should be dumb and receive parameters or inject services.
Hard to know without working on the actual implementation, but you probably want your carousel items to be dumb components, and in terms of the topic of the video it is easier if we have state/data flowing in one direction (e.g. from the parent down). If you do need the items to affect state up stream then you would generally have the components emit an event that would be incorporated into the state of the parent, which technically you can do declaratively with viewChild and getting a reference to the event observable directly, or you might prefer to just "break reactivity" here and have the event callback next some subject/set some signal that is part of the carousel state.
Can I just keep using Rx ? I was so comfy with it
Pretty much the one benefit you get with signals vs observables, is signals will trigger the change detection even in on push components. I have not really felt the need to move away from my existing ngrx (if the project uses it) or service hosted Behavior/Replay Subjects
My comment somehow dissapeared...
So, how do you get something from external API using httpClient and set some signal as a result withou relying on some other library like NgRx or rxjs-interop?
What exactly could go wrong if you subscribe to an observable inside an effect and set signal in subscription callback?
I wouldn't consider rxjs-interop another library since it is included in core, but as you're probably aware httpClient -> toSignal would be the most straightforward way out of the box. As for a signals only solution, Angular doesn't really have that yet, but hopefully we see something on that front soon.
As for subscribing inside of an effect there are some dangers here in that a subscription is going to be created every time the effect runs, which not only has the potential for memory leaks if not carefully managed, but even if managed carefully it will still create race conditions, e.g. a signal the effect references updates again before the previous request has finished, so now you have two requests running on separate subscriptions racing to set a signal when they complete. On top of that, if it's something you care about, you lose the declarative connection where otherwise you could have your data source connected right through to where it is used in your application, but an effect/subscribe (instead of something like httpClient -> toSignal) loses that connection.
@@JoshuaMorony thank you for your reply, I agree with all of that, but... knowing it all, if you still decide to subscribe inside an effect and set some signal, is there anything else that could go wrong that causes angular team to be so loud about not updating the state inside an effect?
Beside race condition (that could be mitigated), and breaking declarative approach (which is a personal decision in this case), I don't see any issues with that solution, as long as you're aware of what you're doing and you're doing that intentionally. Am I wrong?
@@mnemanja if you're already using RxJS anyway doing this inside an effect is just a more fragile/dangerous way to go about it, for the reasons mentioned its all downsides/no upsides. If your goal is to not use RxJS at all I think it makes a bit more sense as there isn't really a vanilla alternative right now. If you were to have an effect that uses the Fetch API to make a request/set a signal then I think it is more reasonable (especially if you don't care about declarative code). But you would still need to do some extra work if you want similar features to the RxJS approach (e.g. supplying a cleanup function to the effect that will trigger the AbortSignal for the fetch request)
@@JoshuaMorony Thanks, makes sense. The one issue I still have is that rxjs-interop is still marked as developer-preview. That makes me a bit anxious to implement it in a production system...
@@mnemanja if it makes you feel any better effect is still in developer preview too ;)
we have two world to handle state but you should probably avoid mangling both
defensively not the case, try to make an Observable HTTP call and convert it to a signal using "toSignal" and without any subscribe you can freely use in template multiple times without worrying to subscribe or unsubscribe
@@ryzottyou do not need to unsubscribe from http client observables anyway. I used to always add on a pipe take 1 to http calls and then one day I found out http client subs auto unsub. I still add them to a subscription however and unsub the subscription OnDestroy. This is for if the component gets destroyed before the http call is finalized.
You also probably shouldn't be using a http call in your template. Fn calls in templates bloat change detection iterations
Recently I run into a situation in which I didn't know how to avoid using an effect: I have a list with an scroll bar which the user can navigate with up or down kbd arrows. I created an effect that checks the focused item index and scrolls the list to that item using the scroll into view on the element reg native element. Any ideas how to do this without effects or in a declarative way?
Sorry, autocorrect: scrollToView on the ElementRef native element
You are using an event and to achieve reactivity with events is to use fromEvent operator it will listen to the event that in your case is scroll and the you can add further functionality and all that will be reactive
Thanks! The scroll is not the event, but the user pressing the down or up arrow keys, which I'm already listening to. These events change the state signal that contains the focused item index. I apply an effect on that signal to move the scroll bar to. So I think this is okish, since it's at the end of the reactivity stream, and there's no declarative way of doing this that I know of (maybe I could create a directive that scrolls to its element ref when it's focused..🤔)
@@codeSurvivor i think directive will be the nicest option here
effect is the same computed thing with restriction to write signals, so in order to continue reactivity you need to create another variable with computed
A declarative mindset is not easy to develop.
A declarative mindset makes it easier to develop.
Phwoar 🔥
don't useEffect 😂😂
Videos like these tend to preach yet fail to inform what the correct path is.
What do you think is missing? The "correct" path is deriving state rather than using effect/subscribe to create new state, and to generally only use effects for actual side effects that don't affect the state of the application
what about obs.pipe(tap(otherObs.next)) ?
Joshua said about restart reactivity by doing it in subscribe, if you not intend to make anything to the end of the stream, then why use the tap operator ?
In terms of side effects/reactive flow you can consider a tap to essentially be the same thing as .subscribe
@@ryzott
here’s the pattern I tend to use it in:
someCmd$.pipe(
withLatestFrom(state$),
map((cmd, state) => {
return a new state with the commands effect;
}),
tap((newState) => state$.next(newState)));