Тёмный
Rainer Hahnekamp
Rainer Hahnekamp
Rainer Hahnekamp
Подписаться 4,6 тыс.
Welcome to my RU-vid channel!
I'm Rainer, a full-stack developer from Austria specializing in Angular and Spring.
As a Google Developer Expert and a trainer/consultant at AngularArchitects.io, I'm here to share my expertise with you.
Subscribe and stay updated with my latest content! Don't forget to connect with me on X (@rainerhahnekamp).
Комментарии
@ml_serenity
@ml_serenity День назад
Regarding 46:00 I think it's much simpler: the effect() takes an arrow function. If no signals inside that function emitted changed value since last change detection cycle, then the whole arrow function is not executed, but if any one or more have their values changed, then the whole arrow function is executed. Also, I believe it uses reference equality to tell if signal should produce a new value to consumers. That's why immutability of the internal state is so important.
@RainerHahnekamp
@RainerHahnekamp День назад
Hi, what do you mean exactly? The dynamic tracking is an advanced feature and I guess not used in the majority of use cases.
@ml_serenity
@ml_serenity День назад
@@RainerHahnekamp I mean the logic to run or not run the effect lambda is probably determined by whether any one or more of the tracked signals associated with it have a new value or not.
@mohsenarshad1588
@mohsenarshad1588 6 дней назад
This video is beyond awesome, thanks a lot for giving so many details and clear explanation.
@RainerHahnekamp
@RainerHahnekamp 6 дней назад
Thanks a lot! Happy to hear
@DerAlexD
@DerAlexD 6 дней назад
yet one question remains how do i test signalStores
@RainerHahnekamp
@RainerHahnekamp 6 дней назад
I guess, you've already found my other video on how test Signals, right ;)
@DerAlexD
@DerAlexD 6 дней назад
@@RainerHahnekamp Yep thanks :)
@DerAlexD
@DerAlexD 7 дней назад
very good video, so same method applies to my signalStore, or do i have to do something different ?
@RainerHahnekamp
@RainerHahnekamp 6 дней назад
Yes, the SignalStore is an Angular Service which exposes native Signals. All things apply there as well.
@rishukumar7586
@rishukumar7586 8 дней назад
why jasmine karma still exists in v18?
@RainerHahnekamp
@RainerHahnekamp 8 дней назад
Karma does still exist, because they are still working on the migration to Web Test Runner. To be fair, one has to say that Jasmine/Karma doesn't have any issues - it is running fine - so they don't see this task as main priority. Jest will come after Web Test Runner is done and Jasmine will stay (as I said in the video). Btw, in th meantime, I would use Jasmine for a new project. Given the troubles we have with Jest/Angular and the pace of the migrations, I am afraid official Jest support is something we get in 2025. Last year, I had the impression that Jest will already be available in Angular 17.
@rkrao8582
@rkrao8582 9 дней назад
Do you have written this guide somewhere? Like in medium or some ither place? Because audio on this is not so great and putting me off.
@RainerHahnekamp
@RainerHahnekamp 9 дней назад
Hey, unfortunately no. What is the issue with the audio? I mean I know I am not a native speaker but microphone should be quite good.
@pazzuto
@pazzuto 10 дней назад
This is great content as always. The concern I have about moving to standalone components is the bundle size. I haven't taken a deep look into this, but I've read here and there that there's a lot of code duplicated and your app actually grows in size. I'm sure it can be mitigated with lazy loading, but it's something to consider.
@RainerHahnekamp
@RainerHahnekamp 10 дней назад
Hi, where did you hear about the bundle size issue? Could it be that you are mistake standalone with the barrel files? Having a lot of barrel files (index.ts) will problems to your bundler because it might not be able to tree-shake them efficientyl, and you may end up with a huge initial bundle. Regarding Standalone vs NgModule, there is no impact on the bundle size.
@arnoldm5358
@arnoldm5358 10 дней назад
Hi, great video again! I'm using createActionGroup method to organize actions from the source which uses them. This way, different actions can lead to the same effect like calling the loadCustomer method from a service for example. This is where I'm struggling with the facade pattern... How can I implement the customerFacade? Do I have to implement several methods like fromPageXLoadCustom(), fromPageYLoadCustomer()... in order to dispatch the right action? I mean that I don't want to loose the origin of each action for debugging purposes.
@RainerHahnekamp
@RainerHahnekamp 10 дней назад
I see, you are the action hygiene. So you have one facade method per action. If you have multiple actions, then you also have multiple methods. As a side note: If you have multiple actions just for debugging purposes, why don't you add {context: string} property to the action's payload. Saves the the same purpose. On the other side, if you have different load actions, stick to what you have.
@arnoldm5358
@arnoldm5358 10 дней назад
@@RainerHahnekamp Thank you for your reply! So It seems that using createActionGroup method and a facade service is not really appropriate. The source property in createActionGroup method is the interesting property (as well as the organisation of the actions of course) and unfortunately we can't benefit to use it.
@RainerHahnekamp
@RainerHahnekamp 9 дней назад
@@arnoldm5358 To be sure there is no misunderstanding. With "stick to what you have", I meant a facade with one method per action.
@toromanow
@toromanow 18 дней назад
I'm experiencing the following issues: 1) When I uncomment the webserver section in playwright.config.ts, then playwright reports "No tests" 2) In my test *.spec.ts file, await page.goto('') results in an error with no explanation. Thoughts?
@RainerHahnekamp
@RainerHahnekamp 17 дней назад
You typically get that message, if you have an invalid configuration file. Check that your commenting also wasn't applied to some things (parenthesis for example). If you uncomment it, and Playwright works, it is definitely an invalid config. You can post the contents of it here as well.
@toromanow
@toromanow 17 дней назад
@@RainerHahnekamp Actually, found those issues to be specific to Windows. All works fine on Ubuntu.
@RainerHahnekamp
@RainerHahnekamp 16 дней назад
@@toromanow It shouldn't make a difference...
@youpeekayey
@youpeekayey 20 дней назад
Sweet mama, fantastic stuff. Most in-depth guide in this topic that i found on yt. Thanks for this and keep up with great work! And subscribed ;)
@RainerHahnekamp
@RainerHahnekamp 20 дней назад
Thanks Doman, will do. The next "big one" will be about RxJs and a little bit longer.
@youpeekayey
@youpeekayey 19 дней назад
@@RainerHahnekamp ​ Great, RxJS is also very interesting topic so I will surely watch it. Btw. RxJs is broad topic so I'm not expecting that you will touch this subject in mentioned video but for future content you could consider adding to your 'pool of ideas' reactive/declarative vs imperative style of programming in context of RxJs (it's not so obvious for many programmers who are used to write imperative code - me included)
@RainerHahnekamp
@RainerHahnekamp 19 дней назад
@@youpeekayeyI touched a little bit on it. I think that RxJs forces you to do declarative programming and I have seen very often that people overuse that paradigm. So I have an example where I show how simple it can become if you add a little bit of side effects into it. We will see 😅
@rolandjost3823
@rolandjost3823 20 дней назад
Thank you Rainer
@RainerHahnekamp
@RainerHahnekamp 20 дней назад
As always, you are very welcome Roland!
@marcwinner567
@marcwinner567 24 дня назад
Thanks for the vid! Learned something new 🎉
@RainerHahnekamp
@RainerHahnekamp 24 дня назад
Great, I stumbled upon the different behavior in a workshop and thought it might be useful to share.
@dhavalv
@dhavalv 24 дня назад
Thank you Rainer for this video. I always make sure to listen to all of your videos, always learn something not documented
@RainerHahnekamp
@RainerHahnekamp 23 дня назад
Thanks Dhaval, and also for your ongoing support. You are a well-known face to me 👍
@etexalbania7301
@etexalbania7301 25 дней назад
thank you for the video, a question about testing, why haven't you done a video for angular testing with Selenium?
@RainerHahnekamp
@RainerHahnekamp 25 дней назад
I don't see any benefit in using Selenium anymore. I've been using Selenium (Selenide) for so many years, and we had to deal with so many flaky tests that we gave up one time. When Cypress came out, we gave E2E testing with Cypress another chance and were more than happy. Since then, I've never heard that somebody really enjoyed working with any webdriver-based derivate. Since I would not use it, I don't want to make a video about it. I know that there is now WebDriver Bidi. It has been hailed to bring the same quality as CDP (Cypress, Playwright) but download statistics show a completely different picture. Did I miss anything, respectively is there a particular reason why you are asking?
@etexalbania7301
@etexalbania7301 25 дней назад
@@RainerHahnekamp thank you. I asked because a lot of testers QA teams use Selenium from what I see in jobs posts and I wonder why it was not used with Angular in any of your videos, and you are the best person to ask for it when talking about testing 🙂 .Have a great day
@RainerHahnekamp
@RainerHahnekamp 24 дня назад
@@etexalbania7301 Yes, you also have remember that Selenium was the standard framework for more than a decade. In huge environments you don't change that quickly. So I don't think that there will be demand for Selenium developers in the future as well. For new projects, though, Selenium doesn't seem to be the first choice anymore (diplomatically said).
@JOELJOSEPHCHALAKUDY
@JOELJOSEPHCHALAKUDY 25 дней назад
thanks, that was a wonderfull overview
@RainerHahnekamp
@RainerHahnekamp 25 дней назад
You're welcome, happy to hear!
@koempf
@koempf 26 дней назад
great Video :-) thanks Rainer ! top
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Most appreciated Steffen!
@nayrban2187
@nayrban2187 26 дней назад
I was talking with a teammate the other day about how most content explains the easy and "obvious" scenarios, but you also cover real scenarios, so thank you
@RainerHahnekamp
@RainerHahnekamp 25 дней назад
Yes, one has to try it on a more realistic application in order to know if it can keep what it promises.
@aianam5354
@aianam5354 26 дней назад
Thank you Rainer ❤ very helpful
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Thanks Aiana and you are very welcome 🙏
@lindermannla
@lindermannla 26 дней назад
Wowww, excelent tutorial! Thnxz!
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Happy to heaar Leonardo
@MohamedAbdulRaouf
@MohamedAbdulRaouf 26 дней назад
Super as always, thank you Rainer form Egypt 🙌
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Thanks a lot Mohamed and best wishes from to Vienna (🇦🇹) to the land of the pyramides (🇪🇬) 👍
@ShiftedBit
@ShiftedBit 26 дней назад
That's an important issue you are showing here. Thank you for that. I think i will stick with rxjs on the data layer and use signals in components only. I may try out a signal store for state management. Currently I am quite happy with rxAngular StateManagement and event driven reactivity.
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Serwas Markus, yeah so using Signals in the templates is definitely a safe bet. I don't think that we have to use RxJs all the time. There are quite a lot of applications out there who might be well off with relying only on Promises but you need to know when Promises aren't sufficient anymore and you need to level up. I intend to come up with a video on that topic. It is not easy one. Although I have very good connections to the RxAngular team, I still haven't tried it out. Shame on me 😅
@ShiftedBit
@ShiftedBit 26 дней назад
@@RainerHahnekamp I know it sounds odd, but do you think it would make a difference to wrap the promise into an observable and embed it to the computed with toSignal()?
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
@@ShiftedBit I don't know, you could try it out if you want to. I've added the link to the repository. But as I said in the video, it must not concern you that you might miss the intermediate change where the holidays are emptied. If it does, that don't use a Signal for the holidays but an Observable. "The problem" is not the Promise, but the Signal itself which skips some values (glitch-free).
@marcwinner567
@marcwinner567 24 дня назад
@@RainerHahnekamplooking forward to that video sir 🎉
@murhafsousli7191
@murhafsousli7191 27 дней назад
Great tutorial, thanks!
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
You are welcome!
@vutruong4164
@vutruong4164 27 дней назад
Thank you for the bombshell video Rainer! While these Signal APIs vastly simplify how components/directives React to Changes, I feel that we still have not arrived at a good pattern for the Initialization phase of components/directives using Signal APIs. Scheduling Initialization in constructor using the afterNextRender() seems to be the most sensible approach for me, with the added benefit of being SSR-friendly I also tried setting up Initialization using effect() and untracked() but in the end it felt a bit "unsafe" because effect execution is asynchronously dependent on Change Detection Scheduling, which we have very little control over. I am also concerned about when the executed effect is itself an asynchronous fetch, like in your demo (the async search function). ngOnInit, on the other hand does not have access to viewChild() and contentChild(), unless these queries are marked static. Perhaps you can provide more insight regarding the advantages/disadvantages of the above approaches in future videos, when best practices emerge!
@RainerHahnekamp
@RainerHahnekamp 26 дней назад
Hey, it sounds to me like you are afraid of loosing the control over things? I don't see it that way to be honest. Yes, an effect runs asynchronously but if it triggers a side-effect which is also asynchronous (e.g. HTTP request), it doesn't change anything. I was never in control of an HTTP request either. Would it be possible to elaborate your issue a little bit? Can you think of a use case where the new API might be a problem? --- I would be careful when it comes to afterNextRender and SSR. It is not executed on the serve. So your rendered page might be missing crucial content. --- Cheers!
@vutruong4164
@vutruong4164 26 дней назад
I would say it's the timing of the availability of various component signals during the initialization that causes me some confusion. Like if I tried to 1. read an input.required() signal, 2. then fetch some data in an effect(), 3. and then use that data to populate a 3rd-party chartJS node in the DOM using viewChild() => I'm not exactly sure where should I schedule this chain of behaviour, because input.required() cannot be read too early in the constructor (input not yet available error would be thrown), while effect() itself must be scheduled in an injection context (constructor or field declaration), when viewChild() result definitely is not yet available in constructor. With decorator based approach, I would say ngOnInit for reading @Input and fetch data, then afterViewInit for populating chartJS DOM node. I'll need to study that part of your video again to familiarize myself with these new timings. Thanks
@VladiSecuritas
@VladiSecuritas 27 дней назад
voice sound quality is really bad.. please use a proper mic.
@RainerHahnekamp
@RainerHahnekamp 27 дней назад
Yes sir, threw it away after that one and working with a wireless. You can see the difference in the second part.
@gaborballa9614
@gaborballa9614 28 дней назад
wow, thank you! this video is very simple to understand for anyone. I recommend it!
@RainerHahnekamp
@RainerHahnekamp 27 дней назад
Thanks a lot!
@pawezysk3404
@pawezysk3404 29 дней назад
Best Angular tRainer ;)
@RainerHahnekamp
@RainerHahnekamp 27 дней назад
THANK YOU!
@vmark
@vmark 29 дней назад
@51:37 In the constructor, when using an effect and setting type to 'city', it knows not to update it because its the same value as it was before. What if instead of type being a string, it was an object? where we set a property of an object? Does it deep compare objects as well? or does it compare only the primitive types for detection?
@RainerHahnekamp
@RainerHahnekamp 27 дней назад
Hey, nope for the deep compare. The signal does the equal check based on object reference. That's why a you need to do an immutable update of the state, i.e. clone the object. You can add an equals function, as second parameter of the computed function. Then you are in charge. That is something I haven't shown in the video.
@siebedom
@siebedom 29 дней назад
Great video, very clear explanation, thank you very well!
@RainerHahnekamp
@RainerHahnekamp 29 дней назад
Thanks as well. And if someting is unclear and you have any questions, let me know!
@votok2
@votok2 Месяц назад
Hi how do you feel about calling a private method in a computed signal that could hide a lot, i.e. what signal(s) the computed one depends on? I kind of try to read the signals value first and pass them as function parameters for better readability...
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Hi, you would have to show me some kind of code so that I can get an understanding of your use case. In general, I would avoid calling methods inside a computed. You don't know what the private method is doing exactly. If the method calls another Signal you have an implicit/hidden tracking of that one. If your method starts an asynchronous task, then you are problay using it wrong and have to find further workarounds, which doesn't really improve the code. On the other side, if the computed is derived by a very complicated algorithm which you want to re-use outside of the computed as well, then yes. That makes sense. But please be free to share a code snippet. You might have a use case I haven't thought about so far.
@MohamedAbdulRaouf
@MohamedAbdulRaouf Месяц назад
Can you share your IDE setup & extensions
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Hi, I am using IntelliJ with the default settings.
@MohamedAbdulRaouf
@MohamedAbdulRaouf Месяц назад
@@RainerHahnekamp Thank you, really enjoyed the video 🙏🙏
@avonzo
@avonzo Месяц назад
I've subscribed. You're superb! Both in terms of explaining and choosing the content! Bottom right useful. Already shared your video with my Java circles. Wonderful work!!
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Hey, thanks a lot. Guess that means, I have to come up with further Java-based Videos...
@donwald3436
@donwald3436 Месяц назад
Good video good explanation, light theme is the devil lol.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Hey! Thanks, I use dark theme occassionally but always come back to the light mode. Can't help myself 👺
@donwald3436
@donwald3436 Месяц назад
@@RainerHahnekamp Well some day you'll get old too.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
@@donwald3436 Well, that's exactyl why I need the light. I don't see so well anymore 😅
@artjomsfomenko757
@artjomsfomenko757 Месяц назад
Some time ago we had services as a 'store', then we went to ngRx, now we go to signal store - which is basically a service. So tell me where is the win? I mean withComputed = getter where you can specify some calc logic
@papastepano
@papastepano Месяц назад
Source: Window.addEventListener:message seems to be triggering change detection all the time
@tarquin161234
@tarquin161234 Месяц назад
Your example on toSignal() appears a simple solution, but in my experience, sometimes it is not appropriate to provide an arbitrary initial value, in which case signals don't work. I think this is an anti pattern. To me it seems more logical an architecture to wait for the real value from the database, rather than scattering around arbitrary starter values, which may have unexpected consequences (e.g. in effects that do calculations).
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Well, I wouldn't say it is an anti-pattern. Especially not in the way how I used it. If it comes to HTTP Response, as you mentioned it, it is a little bit more complicated. First of all, a Signal forces us to provide a value. The alternative would be to have a union type with undefined. Sticking to an Observable is not really option if we consider that Angular is heading towards Signal Components. Another option is that you add metadata to that Signal which tells you, if you already have the response or if the signal's value is still the initial one. But again, with that approach you'll find yourself very quickly in a situation where you want to use a Signal-based state management library. So it starts to become more complicated although you might have a simple use case.
@davesharman8302
@davesharman8302 Месяц назад
Hmmm, with anglar 18, adding @ngrx/signals fails with resolve dependency errors (both with ng add and npm install). Are we expecting a bump in the ngrx signals soon, or is there a workaround? does npm i --force work properly in this case?
@RainerHahnekamp
@RainerHahnekamp Месяц назад
--legacy-peer-deps is the recommended option. See here: github.com/ngrx/platform/issues/4352
@davesharman8302
@davesharman8302 Месяц назад
@@RainerHahnekamp Perfect, thanks for the reply. I have been greatly enjoying your videos on signals and the signal store.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
@@davesharman8302 Thanks Dave. Happy to hear that 😄
@tejeshwinidugyala9226
@tejeshwinidugyala9226 Месяц назад
Best Video for understanding OnPush Strategy so Far :) thank you so much
@RainerHahnekamp
@RainerHahnekamp Месяц назад
You are very welcome. With Angular 18 markForCheck will now also trigger the change detection. Maybe I have to release an updated video.
@leiayuri
@leiayuri Месяц назад
Hi, would you know if I have a component A which extends a directive B. And in comp. a I am in injecting a service A with inject and inside of the constructor I am also calling super and injecting the service A. The question is, am I creating 2 instances os service A? Thanks in advance.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Dear Yuri, could you maybe provide me a small code snippet? Thank you
@leiayuri
@leiayuri Месяц назад
@@RainerHahnekamp see if that peace helps. private processStepPackService: ProcessStepPackService = inject(ProcessStepPackService); constructor(){ super ("ProcessStepPack", inject (ProcessStepPackService)); } In that case where I am injecting ProcessStepPackService twice. Would that be 2 instances or still just one?
@RainerHahnekamp
@RainerHahnekamp Месяц назад
@@leiayuri Ah, that should be just one. You would get multiple instances with different provides but not by calling inject multiple times
@leiayuri
@leiayuri Месяц назад
@@RainerHahnekamp thank you so much. It was very helpful.
@donwald3436
@donwald3436 Месяц назад
huh signals replace ngrx tho?
@RainerHahnekamp
@RainerHahnekamp Месяц назад
If you mean the redux pattern of the globa store, then yes. If you say Signals will replace State management libraries then I would definitely say no. Because you have Signals and a structure that is suited for state management, you need a library on top of it. This is something which has already been confirmed by Angular itself. They said, the default signal function will not be enough as soon as your Signal contains larger values.
@michaeljuliano8839
@michaeljuliano8839 Месяц назад
Vielen Dank! Sehr hilfreich.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Bitte schön. Gerne geschehen der Herr 😉
@awesomewidgets4298
@awesomewidgets4298 Месяц назад
Hi Rainer. Brilliant video, thanks for taking the time! We usually cover DOM testing using Cypress E2Es. Do you think there is any advantage using DOM based tests in our unit tests too? We had been simply "newing" components before and supplying mocks in the constructor (without TestBed). Looks like we've have to move to TestBed in any case to use effects in the constructor.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Yeah, so independent that you don't have any other options to test effects, you need to ask yourself what benefits you get of non-DOM tests? I guess, you are directly calling methods of your TypeScript component then? If yes, here is an official statement from the Angular team on that topic: github.com/angular/angular/issues/54438#issuecomment-1971813177 Tests without DOM access are usually done against Services or heavy-logic based functions.
@awesomewidgets4298
@awesomewidgets4298 Месяц назад
@@RainerHahnekamp Thanks Rainer! Yeah, we normally call the functions directly and test that the logic is correct. We do extract a lot of the logic into standalone (pure) util functions a lot of the time and test them separately. My thoughts were that DOM tests will test the angular wiring which is already tested by Cypress, but from your video I can see the benefit that you can refactor and the tests will still run (and still be meaningful) as they are abstracted a little from the nitty-gritty of the implementation. They are also a lot faster than e2e tests.
@termobin
@termobin Месяц назад
I would like to congratulate you for the excellent work you did in this video, great explanations
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thank you very much. Very nice of you to say that!
@devbuilddeploy
@devbuilddeploy Месяц назад
What I found here just Gold, You can't ask better explanation this, thanks for great work you've done here.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thanks for the compliment!
@mcdona22
@mcdona22 Месяц назад
very very good
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thanks!
@danywalls
@danywalls Месяц назад
Amazing content as always!!!!!
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thanks Dany and best wishes!
@sheariley1910
@sheariley1910 Месяц назад
Effects don't see all value updates because the JavaScript event loop is single threaded and the effects are only executed after the current execution context has finished and the deferred event loop is drained. I'm pretty sure the only way that computed signals and effects automatically register their dependencies is that they record what signals are called during their execution; and more importantly this is only possible because JavaScript is single-threaded. I assume that there is a global register that is used to accumulate a list of called signals during the execution of an effect or computed and that is used to register the dependencies and listen for updates. This only works if only one effect or computed is able to be executed at a time.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
You are absolutely right with your description on how computed and effects register themselves. I would describe the execution of an effect a little bit different though. It is when Angular decides that it is now time to start updating the DOM. So effects run asynchronously but if you have scheduled asynchronous task with a timeout, the the effect will run before them.
@sheariley1910
@sheariley1910 Месяц назад
@@RainerHahnekamp If that is the case (setTimeout executes aftwards), then that means the effect is executed within the same callstack as the update to the dependency signal and does not use the JS event loop. The event loop processes queued tasks (aka messages) sequentially, in the order in which they are added to the queue. It is my understanding that there is no way to prioritize those tasks, other than using the delay argument of the setTimeout and setInterval methods.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
@@sheariley1910 Angular itself is the one that triggers the effect when it does the change detection. So it is not like the effect is natively executed by the engine. You could also see it in a different way. The signals update their consumers immediately about the change. So the consumers always know that they are "dirty" but it is up to the framework when to actually tell them "to put their cards on the table". I've tried to explain it in my video with the animation where I used the term "caller". I might also quote from the official documentation, where they say the time when the effect is called is unspecified: github.com/angular/angular/tree/main/packages/core/primitives/signals#side-effects-createwatch
@sheariley1910
@sheariley1910 Месяц назад
@RainerHahnekamp Angular is written in JavaScript and runs in the JavaScript environment. So I'm not sure what you mean by "the effect is not executed natively by the engine". Angular's signal framework code is either executing the dependent effects as part of the callstack initiated by an update to a dependency signal or it is queuing that execution as a deferred task which is processed by the event loop. Its one or the other. Those are the only 2 possibilities. So if what you are saying is true, then it has to be the former. This is fine. I was just making an observation. Also, this should make it easier to follow the stack trace when debugging and makes the whole thing more deterministic; both great things.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
@@sheariley1910 I hope we don't misunderstand each other and talk about two different things. Angular has an own scheduler when the effect execution happens. When it comes down, it will of course be the JavaScript engine that runs it. You can find the scheduler here: github.com/angular/angular/blob/main/packages/core/src/render3/reactivity/effect.ts Little bit complicated but you get the idea.
@sheariley1910
@sheariley1910 Месяц назад
Any other devs having knockout.js flashbacks?
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Not me :). I skipped knockout.js and went to Angular straigt from ExtJs
@bellosthomas
@bellosthomas Месяц назад
Excellent video. Many thanks. Been using react for sevral years, with mobx for state management. Signals seem very close to how mobx works. What is your thought on using signals for application state as well?
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thanks, so representing state which changes over time is the primiary purpose of Signals. Or did you mean as an alternative to a full-blown state management library?
@bellosthomas
@bellosthomas Месяц назад
@@RainerHahnekamp as a full blown state management system
@RainerHahnekamp
@RainerHahnekamp Месяц назад
​@@bellosthomas Ah, I see. So I don't think this is a good idea because you need a little bit more functionality. For example dealing with parts of the Signal, and improving updating them. Usually there is always some logic around Signals which you also want to have next to the Signal itself. In this case, a state management library which is built on top of Siganls does make sense. I would go with the Signal Store (I've actually made two topics about it, I'd recommend the second one as a starter). You might be interested in watching this Short as well, where Alex Rickabaugh, tech lead of the Angular framework, discusses the same question: ru-vid.comvgzC9xHedyw
@bellosthomas
@bellosthomas Месяц назад
@@RainerHahnekamp if am not mistaken ngrx is the redux counterpart of react. I am not a fan of redux so I try to avoid it. Will check the link. Many thanks
@RainerHahnekamp
@RainerHahnekamp Месяц назад
​@@bellosthomasSo NgRx has the global store, the component store and now the signal Store. The global store is the one with the redux pattern. Signal and Component Store are without it.
@davesharman8302
@davesharman8302 Месяц назад
Very nice video, I learned a lot from it that was very fuzzy before.
@RainerHahnekamp
@RainerHahnekamp Месяц назад
Thanks for the compliment Dave
@SonPham-zy2zp
@SonPham-zy2zp 2 месяца назад
A really nice demonstration. I have a question, If I have 2 signalStore for Customer and User for 2 different pages. I have a global loading bar, how can I apply isLoading on the global component
@RainerHahnekamp
@RainerHahnekamp 2 месяца назад
Hi, please take a look at my example. I have an http interceptor which sets the loading status in a service which is then read by the global component. If that doesn't answer your question, let me know and I can provide alternatives.
@SonPham-zy2zp
@SonPham-zy2zp 2 месяца назад
@@RainerHahnekamp I see that interceptor but sometimes we have calls that we don't want to show a loading bar. I have just come up with the idea of making a LoaderStore with isLoading property. Inject this store into withMethods of each Entity store where I want to show or hide the loading bar. This LoaderStore will be injected in LoaderComponent and bind isLoading into our HTML element. I am not sure if this is also the correct way to do it.
@RainerHahnekamp
@RainerHahnekamp 2 месяца назад
​@@SonPham-zy2zpIf it is just about being able to exclude certain requests from not showing the loader spinner, please take a look at the HttpContext. Whenever you execute an HTTP request you have the option to add contextual data to the request which could be read by the interceptors. For example I use the context for a specific error message. You can find it at github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/shared/http/error-message.context.ts. If you need more option, then going with a service as you did is definitely something I would also then. If it is just about a simple property, I think I would skip the Signal Store for that and just use a simple Signal.