This is great, currently introducing this at work - a lot thanks to your tutorials. On that note I've learned greatly overall from your videos, so a big thanks to you! Would absolutely LOVE a guide or pointers on how to unit test signal stores, not much documentation/articles out there yet. (In my specific use case we're still on jasmine/karma) ...(minutes after I wrote this comment I found ngrx gh issues where you're literally addressing this so I'll just bide my time :) )
Hi Reainer, I use signal store in my DDD application. Mostly, I defined the store in my top smart component and use it down to the dumb one. I recently moved my HTTP request from the store to a dedicated HTTP service to light the store code. I have to call other store from my store, for exemple, an store that need the current logged user will ask the authStore for it. It is correct to do that like its break a little bit the DDD and force me to add some exceptions to my Sheriff config. Thank.
Hi Pierre, if your Domain SignalStores require access to things like UserStore, AuthStore, it is fine. I usually put UserStore, AuthStore - or generally speaking - Services which multiple domains require, into the shared folder. Then you are not breaking any Sheriff rules, because type:data can access domain:shared. If we are talking about one "Domain SignalStore" accessing another "Domain SignalStore", you need to come with exceptions. You can find an example for that at github.com/rainerhahnekamp/eternal/blob/main/sheriff.config.ts
Thanks for explaining with such simplicity and clarity. If we manage auth state via signal store like user info, token, expiry etc, is it better to keep auth service separate for login and logout functions? Or should be added in withMethods block?
Hey, thanks! When a method involves a lot of logic, I extract that logic into a dedicated service. Then, in my withMethods, I call the service directly. For example, I created a KeycloakService to handle authentication, which is used by my SecurityStore.
Quite informative, clean explanation; definitely will be using it. But, also two questions: - why not import tap, etc from 'rxjs' instead of 'rxjs/operators'? - why not use tap({next: ..., error: ...}) instead of tapResponse ???
Thanks, happy to hear. About your questions: tapResponse is like tap but also comes with error handling built-in. That is in case of an error it returns an empty Observable. You've caught a bug; the tapResponse after the switchMap doesn't help; it should be put into the switchMap.
@Rainer another great video from you. I truly appreciate the amount of knowledge you are providing to the community. Really amazing to see your enthusiasm. Thank you very much!!! One of the things discussed in our team is what developer preview means. Although ngrx signals is not in dev preview, it uses effects under the hood. Then how does Ngrx signals be not in dev preview 🤔
For the record, I find it a little bit problematic that effect is in developer preview. If the Angular wants, they can introduce breaking changes with every major release. So effect could be stable and there wouldn't be such much "confusion". That being said, the effect in the SignalStore is used only once, and that's in rxMethod. It is used as an internal implementation, meaning the API doesn't expose it. In case of a breaking change of effect, we would only have to guarantee you that rxMethod works as before. We can change the internal implementation or tweak the effect however we want. So I don't necessarily see it therefore that the SignalStore has to be in developer preview.
Hi Rainer. Thank you for the great video! It helped me a lot to understand how ngrx signal store works. I have a question. How do I add multiple inputs in the signal store feature? For example if i need not only this { state: type() }, but one more parameter. Thanks in advance.
@@RainerHahnekamp I've been coding Angular since version 2 and to be honest, I've never used a state management library, I just used some handmade services with some BehaviorSubject, mostly because of projects being simple. But now, working on more advanced projects, I've decided to have a look into signals and this whole ngrx signals just blew me away! Now I'm a little in doubt about what we should put into a component... Can we say that, we should use an store all the time, and a component should only be responsible for the layout, data formatting and handling UI events? It seems to me that most of the things that I've used to do in a component, can now be easily done inside a store; but I'm not sure it would make sense for small use cases. What do you think about this? What should be inside a component, and what should be inside an store? If a component has some local only state, does it make sense to define store for that or just, when we want to share data in a cross-component way? Sorry couldn't stop my curiosity. Thanks in advance for all of your time and effort, Helping people have a better time coding in Angular!
Thanks for the great explanations. I have a question. I've checked everything, but I don't have access to the store properties (signal state properties) from the template. I can only access the signal store methods from the template. Have I overlooked a setting?
Actually, no. Can you verify if it is "just" an error coming from your IDE or if the Angular compiler (ng serve) throws the same error? The Signal Store uses advanced TypeScript typing, so IDEs might be a little behind.
Thank you for this great video. How can we reset the state of part of the data of the store? Another question is: you were talking about global store, does it means that in a bigger project we could work with multiple store?
I would store the initial state in a variable and come up with a reset method which patches the state with the initial value. You can have as many signal stores as you want.
First of all, thank you very much for your content, it is very good. Now I have a question, is it recommended/good practice to access the Store from the template?
Thanks. If it is like in my example that the service provides already the data and the event listeners "bite-sized for the template", I'd say yes. The more generic the service becomes, the more I'd tend ont to use it directly in the template. So summarized, for local state management, probably yes, for global... very likely not.
Hi Ranier great video as always, a quick question, in your signal store you use the variable name store for with methods but state for withComputed. Is that personal preference? I frequently find myself debating this with myself is it a store or is it the state 🤔
@@andyhb1970 There is a difference. withComputed only gets the state and not access to the methods you might have defined before, whereas withMethods has access to everything. Just clone my example and you will set that withMethods has all the methods of withCountdown and withComputed doesn't.
@@RainerHahnekamp I mean the initial value in the withState part of the feature store. I don't know if the first state value is before or after the interval triggers, so there may be a "glitch" in the timeLeft value.
@@larshanisch The intial timeLeft will always be shown because it takes 1 second for the first run of the interval. I am relying on the timeStarted. So regardless when the interval starts, the timeLeft will always be updated correctly relative to the timeStarted. Maybe I'm missing something here...
@@RainerHahnekamp I'm talking about the hard coded "timeLeft: 180" in line 18 of withCountdown. What happens, if I initialize the quizstore with a different value of timeInSeconds (line 24)? I'm not sitting at my computer ATM so I cannot try... 🤓
@@larshanisch Ahhh, now I get it. Yeah of course. So for a real world project, I would add a loaded status to the state and I'm not going to show anything unless my quiz has been loaded. The the problem with timeLeft doesn't exist.
Thanks a lot for the video! I have a question, and I'll be grateful if you (or someone else) could help me: How can I get data from store by props? for example, get a list item by id, or search items by name
Thanks Rainer for the helpful video! I have a couple of questions about Signal Store: 1. Is it possible to reference values from another store in computed properties, or does the concept of Signal Store oppose this? 2. Does any existing Redux plugin work with Signal Store, or are there alternatives available? Thank you!
Hi Kiril, thanks as well. 1. Yes, you can reference Signals from other Signal Stores in your computeds. In the end they are all native Signales 2. Have you tried out github.com/angular-architects/ngrx-toolkit for Redux? If yes, and it doesn't work let me know. Cheers!
Thank you for the video Rainer, really informative! I have a question/inner reflection; Assume you have a questions page, with a method 'loadAll' that you wanna have provided in route. What is your approach on this? CanActivate guard and return true? Resolver and return true? It seems slightly awkward to me and I am juggling between best approach.
I don't use resolvers when I have state management. What I do instead, to go with guards. The guard triggers the loading and might wait until the store returns the OK that it has loaded the data. Not sure, if this was what you were asking for. If not, please clearify.
@@RainerHahnekamp Thank you, much appreciated the response! One last thing that I would like to hear your opinion on it. Let's say in one page you call `loadAll`, would you also call in CanDeactivate context a store method 'resetAll' that resets questions to initial state?
@AenGex Probably not; if you say loading and destroying is bound to the route, then that sounds to me like a state for local state management. Do you have a component which is bound to that particular route? If yes, then the component should provide the Store. The store has an onInit hook where it loads the data. When the user leaves the component, the Store gets automatically destroyed. If your use case is more complicated than I think, then there might a reason for the guards.
@@RainerHahnekamp Thank you, I understand your point. I don't have a use case in particular, but rather thoughts for common patterns with NgRx. You covered it completely! Thank you for the input and your awesome work!
Hi Rainer, when running the ng update command does this set all signal stores to protectedState: false regardless of whether patchState is used outside of the store or not?
@@RainerHahnekamp ah good, good I thought I was doing something strange to cause it to do that, all my state changes are encapsulated I see that as one of the distinct benefits of using the signalStore 🙂
@@andyhb1970 Yes, yes, so in the release, encapsulation was not just introduced but also defined as best practice. That's why it is now the default behavior. In order not to break existing code, the encapsulation had to be disabled but you should definitely check or maybe even refactor the code, so that protectedState is enabled. It looks like there will be even an ESLint rule which marks protectedState: false as warning.
How to deal with deep properties updates? Something like toggling email state which is nested in my state objects: changeEmailNotificationEnabled(emailEnabled: boolean) { patchState(state, { organizationInformation: { ...state.organizationInformation(), emailNotification: { ...state.organizationInformation.emailNotification(), enabled: emailEnabled } } }); }, do i have to copy every level of nesting or is there a better approach?
What exactly are the benefits of using the ngrx signalstore vs writing a custom angular service containing some signals and maybe rxjs functions. For me custom services are way easier to write / read / extend / understand and you are relying on another library
You will probably write something very similar to the patchState and slices - something that generates slices on the fly and makes it easy to update a Signal. You also want to make sure that your self-written services follow a common style so that developers can easily switch between different code parts. Then, you will also need to reuse certain existing features you have written in one service in another. Yes, you can do it all yourself, but at a certain point in time, I say I just take what is already available, battle-tested, and well-known (like NgRx) in the Angular community. I'd like to add that it is also easy to learn and doesn't come with boilerplate code. It is the typical buy-or-make decision. When it comes to state management, I would always choose "buy."
@@RainerHahnekampIn my opinion there is actually a lot of boilerplate. Creating your signal stores with all the with* functions is pretty much boilerplate and adds a lot of complexity and you still have to implement all methods and rxjs logic yourself. I would argue that you gain very little but add a lot of unnecessary complexity and unnecessary "vendor lock in". Another point i see is that especially "junior" guys might not understand whats "under the hood" and wont learn the basics properly
@@staoish An answer to a comment on TH-cam: WIthout the with* function, you are loosing the structure. Then you have a simple Angular service where your developers putting the computeds, logic, DI in different places. The SignalStore enforces that these elements have a specific location. It makes the code more readable - and yes it does that by adding boilerplate. You might be able to do same via ESLint, but somebody has to write that rule as well. An application is not a playground to learn coding. I don't want to have five different, self-written state management services in the codebase. You see where I am heading to? Junior developers should learn the intricacies of Signals but please not in an application that's shipped to end users. An extreme example: You will not let a "Junior pilot" fly a plane with hundreds of passengers. That's why they have simulators. Does that make sense?
@@RainerHahnekamp Yeah we agree to disagree here i think. I would rather teach a junior how to properly write a clean "store service" and explain the necessary concepts and enforce them via pull requests. Especially because i feel the creation of a ngrx signalstore is really complicated compared to a service and in my opinion it does not increase readability but even reduces it Another important point: a newly hired angular developer will get the self written store service concept immeditately and does not have to learn another library. I feel the disadvantages overweigh the benefits by far
das quiz folder finde ich nicht in Deinem github repository... die patchState Function hat sonst keine Neuerung? Heisst Weiterhin bei immutability immerPatchState verwenden ? Ansonsten wie immer super Rainer :-) echt super!
Hi Steffen, danke, danke Mach mich nicht schwach wegen dem fehlenden Repo! Ist eh alles da: github.com/rainerhahnekamp/ngrx-signal-store-release/blob/main/src/app/holidays/feature/quiz/quiz-store.ts Ja, keine Neuerungen beim patchState. Es wurde eher auf "enterprisy"-Features gesetzt und ein bisschen die Erweiterbarkeit verbessert.
Yes, for me, it ultimately came down to choosing between Redux and extensibility. With the features SignalStore now offers-like protectedState, override, and private-it has everything needed for a global store. And within the next six months, we’ll also see a Redux extension for SignalStore. I honestly don’t see any reason to start a new project with the global Store these days.
Thanks for explaining with such simplicity and clarity. If we manage auth state via signal store like user info, token, expiry etc, is it better to keep auth service separate for login and logout functions? Or should be added in withMethods block?
Good question. In general, I try to not overcomplicate things and put everything in withMethods. As soon as the file becomes larger or I have a specific method is a little bit more complicated, then I extract that into an own service. In my application, I have therefore a separate keycloak.service.ts which wraps the keycloak-specific connection.
The best trainer. Thanks for sharing
Thanks for your ongoing support Roland.
It's simply the truth. Your explanations are clear and simple.
This is great, currently introducing this at work - a lot thanks to your tutorials. On that note I've learned greatly overall from your videos, so a big thanks to you!
Would absolutely LOVE a guide or pointers on how to unit test signal stores, not much documentation/articles out there yet. (In my specific use case we're still on jasmine/karma)
...(minutes after I wrote this comment I found ngrx gh issues where you're literally addressing this so I'll just bide my time :) )
Thanks Jonatan, I think the current status of the testing guide is the one that will lands in the official docs.
Thank you very much Rainer for your explanations.
Great content !
Thanks, you are very welcome
Awesome explanation as always, thank you so much @RainerHahnekamp 👏Helped a lot!
👋 Oh, hi Attila. Thanks a lot!
Thanks Ranier, this was a helpful video on the new features.
Thanks, you are very welcome Dave.
Thank you. Very helpful!
You're welcome. Next release is already knocking on the door.
Hi Reainer, I use signal store in my DDD application. Mostly, I defined the store in my top smart component and use it down to the dumb one. I recently moved my HTTP request from the store to a dedicated HTTP service to light the store code. I have to call other store from my store, for exemple, an store that need the current logged user will ask the authStore for it. It is correct to do that like its break a little bit the DDD and force me to add some exceptions to my Sheriff config. Thank.
Hi Pierre, if your Domain SignalStores require access to things like UserStore, AuthStore, it is fine. I usually put UserStore, AuthStore - or generally speaking - Services which multiple domains require, into the shared folder. Then you are not breaking any Sheriff rules, because type:data can access domain:shared.
If we are talking about one "Domain SignalStore" accessing another "Domain SignalStore", you need to come with exceptions. You can find an example for that at github.com/rainerhahnekamp/eternal/blob/main/sheriff.config.ts
Thanks for explaining with such simplicity and clarity. If we manage auth state via signal store like user info, token, expiry etc, is it better to keep auth service separate for login and logout functions? Or should be added in withMethods block?
Hey, thanks! When a method involves a lot of logic, I extract that logic into a dedicated service. Then, in my withMethods, I call the service directly. For example, I created a KeycloakService to handle authentication, which is used by my SecurityStore.
Quite informative, clean explanation; definitely will be using it. But, also two questions:
- why not import tap, etc from 'rxjs' instead of 'rxjs/operators'?
- why not use tap({next: ..., error: ...}) instead of tapResponse ???
Thanks, happy to hear. About your questions: tapResponse is like tap but also comes with error handling built-in. That is in case of an error it returns an empty Observable.
You've caught a bug; the tapResponse after the switchMap doesn't help; it should be put into the switchMap.
@Rainer another great video from you. I truly appreciate the amount of knowledge you are providing to the community. Really amazing to see your enthusiasm. Thank you very much!!! One of the things discussed in our team is what developer preview means. Although ngrx signals is not in dev preview, it uses effects under the hood. Then how does Ngrx signals be not in dev preview 🤔
For the record, I find it a little bit problematic that effect is in developer preview. If the Angular wants, they can introduce breaking changes with every major release. So effect could be stable and there wouldn't be such much "confusion".
That being said, the effect in the SignalStore is used only once, and that's in rxMethod. It is used as an internal implementation, meaning the API doesn't expose it. In case of a breaking change of effect, we would only have to guarantee you that rxMethod works as before. We can change the internal implementation or tweak the effect however we want.
So I don't necessarily see it therefore that the SignalStore has to be in developer preview.
@@RainerHahnekamp thanks for your reply.
@@dhavalv You are welcome, but how do you see it? Would be interested in hearing your opinion as well.
Hi Rainer. Thank you for the great video! It helped me a lot to understand how ngrx signal store works. I have a question. How do I add multiple inputs in the signal store feature? For example if i need not only this { state: type() }, but one more parameter. Thanks in advance.
Hey, you are very welcome!
Just add an another object. Like this:
{ state: type() },
Thanks a lot! I really enjoyed your awesome content. By the way, what's the best way to reach out to you, in case if we have any questions?
Hey, thanks, well you can contact me via LinkedIn or email on rainer.hahnekamp@gmail.com
@@RainerHahnekamp I've been coding Angular since version 2 and to be honest, I've never used a state management library, I just used some handmade services with some BehaviorSubject, mostly because of projects being simple. But now, working on more advanced projects, I've decided to have a look into signals and this whole ngrx signals just blew me away! Now I'm a little in doubt about what we should put into a component... Can we say that, we should use an store all the time, and a component should only be responsible for the layout, data formatting and handling UI events? It seems to me that most of the things that I've used to do in a component, can now be easily done inside a store; but I'm not sure it would make sense for small use cases. What do you think about this? What should be inside a component, and what should be inside an store? If a component has some local only state, does it make sense to define store for that or just, when we want to share data in a cross-component way?
Sorry couldn't stop my curiosity. Thanks in advance for all of your time and effort, Helping people have a better time coding in Angular!
Thanks for the great explanations. I have a question. I've checked everything, but I don't have access to the store properties (signal state properties) from the template. I can only access the signal store methods from the template. Have I overlooked a setting?
Actually, no. Can you verify if it is "just" an error coming from your IDE or if the Angular compiler (ng serve) throws the same error? The Signal Store uses advanced TypeScript typing, so IDEs might be a little behind.
@@RainerHahnekamp It is actually the IDE, Intellij ultimate, shows an error(Unresolved function or method). Thank you for the tip.
@@platzdochich551yeah, that’s unfortunate. I also use IntelliJ Ultimate but always have a look at the output of the ng serve in the console
Thank you for this great video.
How can we reset the state of part of the data of the store?
Another question is: you were talking about global store, does it means that in a bigger project we could work with multiple store?
I would store the initial state in a variable and come up with a reset method which patches the state with the initial value.
You can have as many signal stores as you want.
danke, echt super wie immer!
Merci beaucoup Lisa 😉
First of all, thank you very much for your content, it is very good. Now I have a question, is it recommended/good practice to access the Store from the template?
Thanks. If it is like in my example that the service provides already the data and the event listeners "bite-sized for the template", I'd say yes.
The more generic the service becomes, the more I'd tend ont to use it directly in the template.
So summarized, for local state management, probably yes, for global... very likely not.
@@RainerHahnekamp thanks for your answer 👍
Hi Ranier great video as always, a quick question, in your signal store you use the variable name store for with methods but state for withComputed. Is that personal preference? I frequently find myself debating this with myself is it a store or is it the state 🤔
@@andyhb1970 There is a difference. withComputed only gets the state and not access to the methods you might have defined before, whereas withMethods has access to everything.
Just clone my example and you will set that withMethods has all the methods of withCountdown and withComputed doesn't.
Nice video!
One question about withCountdown: how would you initialize timeLeft with the correct value from the parent state?
Thanks, didn't I do that? I am using the timeInSeconds from the parent state?
@@RainerHahnekamp I mean the initial value in the withState part of the feature store. I don't know if the first state value is before or after the interval triggers, so there may be a "glitch" in the timeLeft value.
@@larshanisch The intial timeLeft will always be shown because it takes 1 second for the first run of the interval. I am relying on the timeStarted. So regardless when the interval starts, the timeLeft will always be updated correctly relative to the timeStarted. Maybe I'm missing something here...
@@RainerHahnekamp I'm talking about the hard coded "timeLeft: 180" in line 18 of withCountdown. What happens, if I initialize the quizstore with a different value of timeInSeconds (line 24)? I'm not sitting at my computer ATM so I cannot try... 🤓
@@larshanisch Ahhh, now I get it. Yeah of course. So for a real world project, I would add a loaded status to the state and I'm not going to show anything unless my quiz has been loaded. The the problem with timeLeft doesn't exist.
Thanks a lot for the video!
I have a question, and I'll be grateful if you (or someone else) could help me: How can I get data from store by props? for example, get a list item by id, or search items by name
Hey, at the moment, that would be a method returning a computed. So you have to put that into `withMethods`.
@@RainerHahnekamp cool! I was thinking about it, but didn't knew if it's the right way. Thanks!
@@simionmarian4395 Yeah, I want to bring that up for discussion for the next version. I would usually see that as part of withComputed
Thanks Rainer for the helpful video! I have a couple of questions about Signal Store:
1. Is it possible to reference values from another store in computed properties, or does the concept of Signal Store oppose this? 2. Does any existing Redux plugin work with Signal Store, or are there alternatives available?
Thank you!
Hi Kiril, thanks as well.
1. Yes, you can reference Signals from other Signal Stores in your computeds. In the end they are all native Signales
2. Have you tried out github.com/angular-architects/ngrx-toolkit for Redux? If yes, and it doesn't work let me know.
Cheers!
@@RainerHahnekamp Thank you for the quick response, I will try it immediately
Thank you for the video Rainer, really informative!
I have a question/inner reflection; Assume you have a questions page, with a method 'loadAll' that you wanna have provided in route. What is your approach on this? CanActivate guard and return true? Resolver and return true? It seems slightly awkward to me and I am juggling between best approach.
I don't use resolvers when I have state management. What I do instead, to go with guards. The guard triggers the loading and might wait until the store returns the OK that it has loaded the data.
Not sure, if this was what you were asking for. If not, please clearify.
@@RainerHahnekamp Thank you, much appreciated the response! One last thing that I would like to hear your opinion on it.
Let's say in one page you call `loadAll`, would you also call in CanDeactivate context a store method 'resetAll' that resets questions to initial state?
@AenGex Probably not; if you say loading and destroying is bound to the route, then that sounds to me like a state for local state management. Do you have a component which is bound to that particular route? If yes, then the component should provide the Store. The store has an onInit hook where it loads the data. When the user leaves the component, the Store gets automatically destroyed.
If your use case is more complicated than I think, then there might a reason for the guards.
@@RainerHahnekamp Thank you, I understand your point. I don't have a use case in particular, but rather thoughts for common patterns with NgRx. You covered it completely! Thank you for the input and your awesome work!
Awesome!!! 👏👏
Thanks Borja!
Hi Rainer, when running the ng update command does this set all signal stores to protectedState: false regardless of whether patchState is used outside of the store or not?
Yes
@@RainerHahnekamp ah good, good I thought I was doing something strange to cause it to do that, all my state changes are encapsulated I see that as one of the distinct benefits of using the signalStore 🙂
@@andyhb1970 Yes, yes, so in the release, encapsulation was not just introduced but also defined as best practice. That's why it is now the default behavior.
In order not to break existing code, the encapsulation had to be disabled but you should definitely check or maybe even refactor the code, so that protectedState is enabled.
It looks like there will be even an ESLint rule which marks protectedState: false as warning.
How to deal with deep properties updates? Something like toggling email state which is nested in my state objects: changeEmailNotificationEnabled(emailEnabled: boolean) {
patchState(state, {
organizationInformation: {
...state.organizationInformation(),
emailNotification: {
...state.organizationInformation.emailNotification(),
enabled: emailEnabled
}
}
});
}, do i have to copy every level of nesting or is there a better approach?
Unfortunately yes. If you go with github.com/timdeschryver/ngrx-immer you can also do a mutable update, though.
What exactly are the benefits of using the ngrx signalstore vs writing a custom angular service containing some signals and maybe rxjs functions.
For me custom services are way easier to write / read / extend / understand and you are relying on another library
You will probably write something very similar to the patchState and slices - something that generates slices on the fly and makes it easy to update a Signal. You also want to make sure that your self-written services follow a common style so that developers can easily switch between different code parts. Then, you will also need to reuse certain existing features you have written in one service in another.
Yes, you can do it all yourself, but at a certain point in time, I say I just take what is already available, battle-tested, and well-known (like NgRx) in the Angular community. I'd like to add that it is also easy to learn and doesn't come with boilerplate code.
It is the typical buy-or-make decision. When it comes to state management, I would always choose "buy."
@@RainerHahnekampIn my opinion there is actually a lot of boilerplate. Creating your signal stores with all the with* functions is pretty much boilerplate and adds a lot of complexity and you still have to implement all methods and rxjs logic yourself. I would argue that you gain very little but add a lot of unnecessary complexity and unnecessary "vendor lock in".
Another point i see is that especially "junior" guys might not understand whats "under the hood" and wont learn the basics properly
@@staoish An answer to a comment on TH-cam: WIthout the with* function, you are loosing the structure. Then you have a simple Angular service where your developers putting the computeds, logic, DI in different places. The SignalStore enforces that these elements have a specific location. It makes the code more readable - and yes it does that by adding boilerplate. You might be able to do same via ESLint, but somebody has to write that rule as well.
An application is not a playground to learn coding. I don't want to have five different, self-written state management services in the codebase. You see where I am heading to? Junior developers should learn the intricacies of Signals but please not in an application that's shipped to end users.
An extreme example: You will not let a "Junior pilot" fly a plane with hundreds of passengers. That's why they have simulators.
Does that make sense?
@@RainerHahnekamp Yeah we agree to disagree here i think. I would rather teach a junior how to properly write a clean "store service" and explain the necessary concepts and enforce them via pull requests.
Especially because i feel the creation of a ngrx signalstore is really complicated compared to a service and in my opinion it does not increase readability but even reduces it
Another important point: a newly hired angular developer will get the self written store service concept immeditately and does not have to learn another library.
I feel the disadvantages overweigh the benefits by far
das quiz folder finde ich nicht in Deinem github repository... die patchState Function hat sonst keine Neuerung? Heisst Weiterhin bei immutability immerPatchState verwenden ? Ansonsten wie immer super Rainer :-) echt super!
Hi Steffen, danke, danke
Mach mich nicht schwach wegen dem fehlenden Repo! Ist eh alles da: github.com/rainerhahnekamp/ngrx-signal-store-release/blob/main/src/app/holidays/feature/quiz/quiz-store.ts
Ja, keine Neuerungen beim patchState. Es wurde eher auf "enterprisy"-Features gesetzt und ein bisschen die Erweiterbarkeit verbessert.
@@RainerHahnekamp stimmt sorry ich hab falsch geschaut :-) Steffen mal wieder ;-)
so today you prefer to use ngrx signal store than ngrx store?
Yes, for me, it ultimately came down to choosing between Redux and extensibility. With the features SignalStore now offers-like protectedState, override, and private-it has everything needed for a global store.
And within the next six months, we’ll also see a Redux extension for SignalStore.
I honestly don’t see any reason to start a new project with the global Store these days.
how to start the server (backend/8080)?
Hey, sorry for the late response. The backend is only available on my machine. I was hoping that the frontend source is enough.
Thanks for explaining with such simplicity and clarity. If we manage auth state via signal store like user info, token, expiry etc, is it better to keep auth service separate for login and logout functions? Or should be added in withMethods block?
Good question. In general, I try to not overcomplicate things and put everything in withMethods. As soon as the file becomes larger or I have a specific method is a little bit more complicated, then I extract that into an own service. In my application, I have therefore a separate keycloak.service.ts which wraps the keycloak-specific connection.