Rainer Hahnekamp
Rainer Hahnekamp
  • 38
  • 156 255
NgRx Signal Store: The Release
In this video, I show the features that were added to the release of the NgRx Signal Store! 🎉
This video is made up of two parts. The first, and longer, is an introduction to Signal Store. The second covers the new features and, therefore, the release itself.
Part 1: Introduction to the Signal Store
✍️ Easy State Management with patchState. It allows you to write and read state much easier.
🧹 Enforced Structure for Derived Values and Logic: The structured approach that Signal Store enforces ensures that your code remains clean and maintainable.
🚀 Extensibility: Build powerful and flexible extensions with signalStoreFeature.
Part 2: New Features introduced with the release
🔒 Encapsulation with protectedState
🚫 Override Protection
🔐 Private state, computeds, and methods:The introduction of private state, private computeds, and private methods, gives you more control over your application’s state management.
👀 watchSignal for Glitch-Free Signals: watchSignal feature helps you overcome the glitch-free effect of Signals when necessary (!).
The repository is available at: github.com/rainerhahnekamp/ngrx-signal-store-release.
The direct link to the QuizStore: github.com/rainerhahnekamp/ngrx-signal-store-release/blob/main/src/app/holidays/feature/quiz/quiz-store.ts
Enjoy the video and feel free to drop any questions or comments below.
Happy coding! 💻😊
Further reading and watching:
- Official Blog: dev.to/ngrx/announcing-ngrx-signals-v18-state-encapsulation-private-store-members-enhanced-entity-management-and-more-2lo6
- NgRx Website: ngrx.io/
- NgRx Signal Store Trilogy, Part 1: th-cam.com/video/V-D2sk_azcs/w-d-xo.html
- NgRx Signal Store Trilogy, Part 2: th-cam.com/video/TLq0OcSshYI/w-d-xo.html
- Signals Unleashed: Full Guide: th-cam.com/video/6W6gycuhiN0/w-d-xo.html
- Reactive Contexts: th-cam.com/video/6AvN-Zqkrkg/w-d-xo.html
Chapters:
0:00 Welcome
0:44 1.0 Application Walkthrough
1:56 1.1 reading/writing Signals: patchState() & Slices
8:08 1.2 Structure: with* Functions
22:45 1.3 Extensions: signalStoreFeature()
30:53 2.0 Preparation: ng update
31:12 2.1 Encapsulation: protectedState
33:23 2.2 private state/methods/computeds
36:15 2.3 Override protection
38:22 2.4 watchState()
43:38 2.5 withEntities()
44:10 Summary and Farewell
มุมมอง: 4 758

วีดีโอ

Reactive Contexts
มุมมอง 2.7K3 หลายเดือนก่อน
In this video, we delve into the concept of Reactive Contexts in Angular and their crucial role in making Signals reactive. You'll learn: 🚦 What a Reactive Context is and why it is essential for Signals. 🚦 How the effect function creates a Reactive Context. 🚦 How a Reactive Context functions within an Angular template. 🚦 The slight differences between the effect function and template Reactive C...
Signals Unleashed: The Full Guide
มุมมอง 23K5 หลายเดือนก่อน
This video is your one-stop guide to Signals in Angular (as of 17.3). We'll dive deep into: ✅ Essential functions: signal, computed, and effect explained. ✅ Reactive Context: Understand where it lives and how to use it. ✅ Glitch-free effects: Why this behavior is a strength, not a bug. ✅ Angular's safety net: Learn how Signals prevent cyclic dependencies and manage side effects effectively. ✅ S...
How do I test Signals (signal / computed / effect)
มุมมอง 3.1K5 หลายเดือนก่อน
Signals as lightweight "reactive primitive" will shape the future of Angular applications. At the time of this recording, signal() and computed() are stable, and effect() is in "developer preview". We see increasing integration of Signals into the Angular API, and there should be no more reason to hold us back from using Signals. What are the requirements? First, we must understand Signals' beh...
How do I test Components & Routing with the RouterTestingHarness
มุมมอง 8535 หลายเดือนก่อน
Tired of writing boilerplate code to test Angular components with router-specific data? The RouterTestingHarness is your new best friend! This video dives deep into this under-appreciated Angular testing tool, showing you how to: - Simplify tests involving ActivatedRoute and dynamic router parameters. - Reduce boilerplate code and write cleaner, more maintainable tests. - Navigate to specific r...
How do test code using inject()
มุมมอง 1.3K6 หลายเดือนก่อน
Angular's inject function has been available since version 14 and was - next to Standalone Components - the star feature. In this video, I explain why you want to switch from constructor-based dependency injection to inject(), although it doesn't make testing easier. A bit about the difference between inject and TestBed.inject and finally, the TestBed.runInInjectionContext, which you require fo...
How do I test and mock Standalone Components
มุมมอง 2.8K6 หลายเดือนก่อน
Angular's Standalone Components offer the advantage of including all their sub-components, directives, and pipes, making them ideal for comprehensive testing of a component's complete functionality. However, there are scenarios where we may want to mock specific parts of the dependency tree, particularly when dealing with a dependency that brings along an extensive set of additional dependencie...
NgRx Signal Store Trilogy, Part 2: The Missing Piece to Signals
มุมมอง 4.1K7 หลายเดือนก่อน
The NgRx Signal Store is more than just a contemporary state management library. It seamlessly integrates with Angular's Signals, inheriting powerful features such as computed Signals, immutability, and reactivity. On top of them, it adds advanced functionalities like patching, automated nested Signals, coupled logic, and seamless integration with RxJs. Join me in this video as we delve into th...
NgRx Signal Store Trilogy, Part 1: Why, When, and How?
มุมมอง 15K8 หลายเดือนก่อน
NgRx, the reigning champion of state management in Angular, has taken a significant leap forward by introducing the NgRx Signal Store. Joining the ranks of the Global and Component Stores, the Signal Store represents the third evolution of NgRx's state management prowess. This video starts with Signals and explores why they necessitate a more sophisticated state management approach. We then shi...
Angular's Change Detection
มุมมอง 7K9 หลายเดือนก่อน
In this video, we delve into Angular's rendering behavior in version 17, examining how Angular responds to changes triggered by user interactions or tasks and how it updates the DOM accordingly. At the heart of this process is Angular's Change Detection mechanism, which operates seamlessly in its default state. However, there are scenarios where fine-tuning is necessary for improved performance...
Introducing Playwright
มุมมอง 3.1K9 หลายเดือนก่อน
This video serves as an introduction to Playwright, a high-performance End-to-End (E2E) testing framework developed by Microsoft known for producing reliable tests. As of the end of 2023, it has nearly caught up with Cypress in terms of download numbers. I'll walk you through the basics of Playwright, such as selecting and interacting with elements, and how to perform assertions. The video also...
OpenAPI with Spring & Angular
มุมมอง 1.9K9 หลายเดือนก่อน
In this video, I explain how to use the OpenAPI for type-safe communication between Spring and Angular. I will also do an application walkthrough, where I explain a minimal Spring application, which uses the latest features of Spring Boot 3 (for example Testcontainers). The GitHub repository is available at github.com/rainerhahnekamp/spring-angular-openapi 0:00 Introduction 1:14 Theory 6:53 App...
GraalVM and Spring
มุมมอง 1.3K10 หลายเดือนก่อน
GraalVM and Spring
Angular Signals enforce Immutability in v17
มุมมอง 2.2K10 หลายเดือนก่อน
Angular Signals enforce Immutability in v17
Cypress and Playwright: A Comparison
มุมมอง 7K10 หลายเดือนก่อน
Cypress and Playwright: A Comparison
NgRx Best Practices - Episode 4: Facade Pattern
มุมมอง 4.6Kปีที่แล้ว
NgRx Best Practices - Episode 4: Facade Pattern
Angular Testing in 2023: Past, Present, and Future
มุมมอง 12Kปีที่แล้ว
Angular Testing in 2023: Past, Present, and Future
Angular Unit Tests with the inject() function
มุมมอง 5Kปีที่แล้ว
Angular Unit Tests with the inject() function
Angular 15: Responsive Images with NgOptimizedImage, provideHttpClient, Directive Composition API
มุมมอง 3.1Kปีที่แล้ว
Angular 15: Responsive Images with NgOptimizedImage, provideHttpClient, Directive Composition API
Type-Safe TypeScript with Type Narrowing
มุมมอง 1.6Kปีที่แล้ว
Type-Safe TypeScript with Type Narrowing
Angular 14.2: NgOptimizedImage & provideRouter
มุมมอง 1.3Kปีที่แล้ว
Angular 14.2: NgOptimizedImage & provideRouter
Angular 14.1
มุมมอง 803ปีที่แล้ว
Angular 14.1
Cypress Component Testing in Angular
มุมมอง 13K2 ปีที่แล้ว
Cypress Component Testing in Angular
Migrating/Updating to Angular 14
มุมมอง 4.6K2 ปีที่แล้ว
Migrating/Updating to Angular 14
Angular Standalone Components and their Impact on Modularity
มุมมอง 8K2 ปีที่แล้ว
Angular Standalone Components and their Impact on Modularity
Deep Linking in a Single Component
มุมมอง 2K2 ปีที่แล้ว
Deep Linking in a Single Component
NgRx Best Practices - Episode 3: Routing & other Deferrals
มุมมอง 2.5K2 ปีที่แล้ว
NgRx Best Practices - Episode 3: Routing & other Deferrals
NgRx createFeature
มุมมอง 1.8K2 ปีที่แล้ว
NgRx createFeature
NgRx Best Practices - Episode 2: Architecture & Modules
มุมมอง 4.5K2 ปีที่แล้ว
NgRx Best Practices - Episode 2: Architecture & Modules
NgRx Best Practices - Episode 1: Cache & LoadStatus
มุมมอง 4.6K3 ปีที่แล้ว
NgRx Best Practices - Episode 1: Cache & LoadStatus

ความคิดเห็น

  • @denissidorenko8832
    @denissidorenko8832 3 วันที่ผ่านมา

    Excellent overview. Detailed and concise.

    • @RainerHahnekamp
      @RainerHahnekamp 3 วันที่ผ่านมา

      Thank you. Happy to hear.

  • @ansumanmishra9608
    @ansumanmishra9608 4 วันที่ผ่านมา

    Why onPush is not the default Change detection strategy? I find it weird the way Angular handles re-rendering of the components. React does it more efficiently.

    • @RainerHahnekamp
      @RainerHahnekamp 4 วันที่ผ่านมา

      Well, you see how much time I have to spend in order to explain the potential issues with OnPush. With the default mode, it just works. So that's the trade-off. On the one side default is big when it comes to developer experience, on the other side it is slower. In my experience, a lot of Angular applications are already fast enough and it is not necessary to use OnPush. That being said, with zoneless introduced as experimental mode in Angular 18, pure-OnPush applications can now also get rid of zone.js and if we stick to Signals, we end up with the same developer experience with the default change detection. Summary: In 2024, use OnPush.

  • @simionmarian4395
    @simionmarian4395 10 วันที่ผ่านมา

    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

    • @RainerHahnekamp
      @RainerHahnekamp 10 วันที่ผ่านมา

      Hey, at the moment, that would be a method returning a computed. So you have to put that into `withMethods`.

    • @simionmarian4395
      @simionmarian4395 10 วันที่ผ่านมา

      @@RainerHahnekamp cool! I was thinking about it, but didn't knew if it's the right way. Thanks!

    • @RainerHahnekamp
      @RainerHahnekamp 10 วันที่ผ่านมา

      @@simionmarian4395 Yeah, I want to bring that up for discussion for the next version. I would usually see that as part of withComputed

  • @spartanghost_17
    @spartanghost_17 11 วันที่ผ่านมา

    This is the best video that I have seen on Graalvm for spring. Very well explained, clear and to the point with all edge cases

    • @RainerHahnekamp
      @RainerHahnekamp 10 วันที่ผ่านมา

      Thanks a lot for the compliment.

  • @DS-bz4mz
    @DS-bz4mz 12 วันที่ผ่านมา

    Great video! It'll take a while for me to really understand some concepts, especially since we haven't been using Signals yet, and we've only just upgraded to v17. However, I'm excited about the future of both Signals and RxJS. :)

    • @RainerHahnekamp
      @RainerHahnekamp 12 วันที่ผ่านมา

      @@DS-bz4mz Thanks, well if you are on 17 now, it is time to make use of them 👍

  • @turkerozturk6889
    @turkerozturk6889 14 วันที่ผ่านมา

    I am trying to gather information to run my application on a Raspberry Pi. I’ve been exploring GraalVM because I need to run my Spring Boot application more efficiently on either a Raspberry Pi or a Linux virtual machine. I was able to successfully create an executable for a simple "Hello World" Spring Boot application on a VirtualBox virtual ubuntu linux server. After spending about 1-2 days researching and experimenting with GraalVM, I watched your video. I still have more to learn and test, but the content you’ve provided is of very high quality. It's clear that after some initial experiments and research, one can find valuable insights in your video. Thank you!

    • @RainerHahnekamp
      @RainerHahnekamp 13 วันที่ผ่านมา

      Hello, hello, thanks a lot. I have just a few Java-related videos but comments like this, are extremly motivating to come up with more. Thanks.

  • @sachindanielvarkey2377
    @sachindanielvarkey2377 15 วันที่ผ่านมา

    Thanks for the video Rainer, One question on this is if I use the DI function imported in some service/component and try to mock the function in the unit test spec it still gives me the ng0203 error. Try to run in the runIninjectioncontext() still showing the inject() error for ng0203.

    • @RainerHahnekamp
      @RainerHahnekamp 14 วันที่ผ่านมา

      Hey, what exactly do you try to mock? Do you maybe have a code example?

  • @UfuUfu-sj3bv
    @UfuUfu-sj3bv 15 วันที่ผ่านมา

    Hi Rainer, long time lurker here, great videos you got you are a natural born teacher and we are very lucky to have you. One small tip for you in regard of your video's audio. I am not entirely sure how it is done, either automatically or applied manually by you or your audio/video-editor, but it seems that you use some form of audio compression on your voice to clarify your speech to a somewhat singular volume level, however, it also activates when you are quiet and is then raising the noise floor, which seems to amplify the surroundings when you are not saying anything, and it also amplifies your breathing :) Like you are suddenly Kirby :) It's not a big deal at all but I just felt i should mention it to increase the quality of your already high quality videos :) Thanks a lot for doing this work and god bless you :)

    • @RainerHahnekamp
      @RainerHahnekamp 14 วันที่ผ่านมา

      Hi, thanks for the info. Can you maybe point me to a quiet section? Would help me if I could hear it as well. I don't do anything manually in terms of audio quality, but maybe the microphone or Premiere does it. Thanks!

    • @UfuUfu-sj3bv
      @UfuUfu-sj3bv 13 วันที่ผ่านมา

      @@RainerHahnekamp It happens basically every time you breathe in or out. It shouldn't be that loud. It's definitely an automated thing, maybe check if your microphone does auto compression or perhaps it's some setting in adobe premiere. I just did some research and it turns out youtube also compresses the audio quite a bit, it is said that it's a bit less when your output volume is lower. Honestly, your videos sound good enough so I wouldn't spend too much time on it, I just mentioned it in case it was something you or your editor did, and perhaps they could dial it back a bit. Keep up the good work :)

    • @RainerHahnekamp
      @RainerHahnekamp 12 วันที่ผ่านมา

      @@UfuUfu-sj3bv Thanks, unfortunately I do everything on my own and I don't have the necessary education when it comes to audio/video recording. In my next video I hear the loud breathing already in the original video file. So it looks it is coming already from the microphone.

    • @UfuUfu-sj3bv
      @UfuUfu-sj3bv 11 วันที่ผ่านมา

      ​@@RainerHahnekamp Well compression is basically the process of making all (or most) parts equal so that the sound source becomes more predictable and with vocals that leads to hearing the result better. It's like pressed down in total, soft sounds and high volume sounds, and then because it got no more unpredictable spikes in loudness, it usually gets turned up a lot. So what's probably happening in your case is that it's simultaneously being compressed down into a singular volume, then raised back up, making breathing sounds as if it was as loud as your normal speaking. There's a very big dynamic range in audio sources, meaning it usually goes from very soft to very loud. You must have noticed it at one point in a movie, the music would be very loud, but the voices would be too soft, so you turn it up and you get your eardrums blasted. The more cheaper streamer material probably does this for you but it makes for uncontrollable results as you've noticed. So investing at some point in a more expensive microphone and audio interface could be a good move to increase production quality. Then you can play around with compression yourself on an unmodified audio source. But it's not easy, doing sound editing, since it's a 3d space you are dealing with. So perhaps it's better to wait until these video's made you millionair and get an audio editor to do it for you :)

  • @michastuleblak4998
    @michastuleblak4998 16 วันที่ผ่านมา

    Great video! Thank you for sharing your knowledge ;)

    • @RainerHahnekamp
      @RainerHahnekamp 14 วันที่ผ่านมา

      Thanks as well, Michael!

  • @BenBeckers
    @BenBeckers 17 วันที่ผ่านมา

    Awesome! Big thanks!

  • @dhavalv
    @dhavalv 18 วันที่ผ่านมา

    @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 🤔

    • @RainerHahnekamp
      @RainerHahnekamp 18 วันที่ผ่านมา

      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.

    • @dhavalv
      @dhavalv 18 วันที่ผ่านมา

      @@RainerHahnekamp thanks for your reply.

    • @RainerHahnekamp
      @RainerHahnekamp 18 วันที่ผ่านมา

      @@dhavalv You are welcome, but how do you see it? Would be interested in hearing your opinion as well.

  • @MrAnother67
    @MrAnother67 18 วันที่ผ่านมา

    Thanks a lot! I'm looking to do the same thing, but I'm using Cypress component testing. Is there anyway to test routing without having to write e2e tests?

    • @RainerHahnekamp
      @RainerHahnekamp 18 วันที่ผ่านมา

      Hi Saeed, honestly, I haven't tried it out yet but you could give it a try. Use cy.mount to setup the router, also use provideLocationMocks and try to navigate with the harness. If it doesn't work, let me know and I'll give it a try. Should be doable in my opinion.

  • @OlehBiblyi
    @OlehBiblyi 19 วันที่ผ่านมา

    Thank you Rainer

  • @wol1414
    @wol1414 19 วันที่ผ่านมา

    Super!)) I`m understanding how it works. Thank you!)

    • @RainerHahnekamp
      @RainerHahnekamp 19 วันที่ผ่านมา

      Great, you're welcome

    • @wol1414
      @wol1414 19 วันที่ผ่านมา

      ​@@RainerHahnekamp can you explain how to make something like that work? loadVideos$: Observable<Action> = createEffect(() => { return this.actions$.pipe( ofType(VideoActions.loadVideos), switchMap(() => computed(() => this.searchService.searchQuery$).pipe( this switchMap((query: string) => computed(() => this.navigationService.currentTokenPage$).pipe( and this switchMap((pageToken: string) => this.requestService.search(query, pageToken).pipe( switchMap((items: Item[]) => this.filterService.filter$.pipe( map(() => this.filterService.sortDataByFilterCriteria(items)) ) ), map((videos: Item[]) => VideoActions.loadVideosSuccess({ videos })), catchError((error) => of(VideoActions.loadVideosFailure({ error: error.message }))) ) ) ) ) ) ) })

  • @techincalExpert
    @techincalExpert 20 วันที่ผ่านมา

    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?

    • @RainerHahnekamp
      @RainerHahnekamp 20 วันที่ผ่านมา

      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.

  • @rororlo
    @rororlo 21 วันที่ผ่านมา

    I've been fighting against this problem for hours, thanks for the video, all really clear!

    • @RainerHahnekamp
      @RainerHahnekamp 21 วันที่ผ่านมา

      Thanks, great to hear.

  • @user-hs9uf8fg5k
    @user-hs9uf8fg5k 23 วันที่ผ่านมา

    how to start the server (backend/8080)?

    • @RainerHahnekamp
      @RainerHahnekamp 10 วันที่ผ่านมา

      Hey, sorry for the late response. The backend is only available on my machine. I was hoping that the frontend source is enough.

  • @Nabulio85
    @Nabulio85 23 วันที่ผ่านมา

    Thank you very much for sharing your knowledge. Great content.

  • @NoName-1337
    @NoName-1337 27 วันที่ผ่านมา

    Just a fassade or a real private variable?

    • @RainerHahnekamp
      @RainerHahnekamp 26 วันที่ผ่านมา

      It is not real private. So if you do an (store as any)._updateTimeLeft() it would work.

    • @NoName-1337
      @NoName-1337 26 วันที่ผ่านมา

      @@RainerHahnekamp would it be better to use #? Or is it not possible in the internal structure?

    • @RainerHahnekamp
      @RainerHahnekamp 26 วันที่ผ่านมา

      @@NoName-1337 the # is only allowed for class properties. withMethods doesn't return a class but an object literal. that's the problem.

    • @NoName-1337
      @NoName-1337 26 วันที่ผ่านมา

      @@RainerHahnekamp true, you're right. totally forgot about that point.

  • @raknjarasoa
    @raknjarasoa 27 วันที่ผ่านมา

    Why not, not returning private methods from return object ? In that’s way, I think that it still accessible by other methods 🎉

    • @RainerHahnekamp
      @RainerHahnekamp 26 วันที่ผ่านมา

      You cannot set properties of an object as private. You can only do that if you have a class.

    • @raknjarasoa
      @raknjarasoa 26 วันที่ผ่านมา

      @@RainerHahnekamp My point is to add the private function ""updateTimeLeft" before withMethods return. Eg: withMethods((store, http = inject(HttpClient)) => { function updateTimeLeft() { console.log('Private function'); return 'Hello'; } return { loadExchangeRates: rxMethod<ExchangeRates>( pipe( switchMap(() => { updateTimeLeft();

  • @connieleung96
    @connieleung96 27 วันที่ผ่านมา

    Amazing

  • @Nabulio85
    @Nabulio85 28 วันที่ผ่านมา

    Thank you very much Rainer for your explanations. Great content !

    • @RainerHahnekamp
      @RainerHahnekamp 28 วันที่ผ่านมา

      Thanks, you are very welcome

  • @elhadjibrahimabalde1234
    @elhadjibrahimabalde1234 หลายเดือนก่อน

    Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.

  • @shashikanthbuddhiol6127
    @shashikanthbuddhiol6127 หลายเดือนก่อน

    If we update signal in an effect not aware of it could go into infinite loop. Will angular gives any warning? I think while implementing complex functionality developer may get into updating multiple effects that can lead to infinite loop, it is better angular should warn.

    • @RainerHahnekamp
      @RainerHahnekamp 28 วันที่ผ่านมา

      So first of all, you have to disable the built-in protected via untracked or allowSignalWrites. Once it is disable, you are responsible for whatever you do: n = signal(1); #loop = effect( () => { console.log('loop'); this.n.set(this.n() + 1); }, { allowSignalWrites: true }, ); That is an infinite loop. Very easy to achieve 😇

  • @elhadjibrahimabalde1234
    @elhadjibrahimabalde1234 หลายเดือนก่อน

    hello i have start your tuto yesterday, but when i run your git repo, i have;---/**--- We are sorry. An error happened.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Hi Ibrahim, can you help me here a little bit? Which commands returns that error?

    • @elhadjibrahimabalde1234
      @elhadjibrahimabalde1234 หลายเดือนก่อน

      @@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.

    • @elhadjibrahimabalde1234
      @elhadjibrahimabalde1234 หลายเดือนก่อน

      @@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.

    • @elhadjibrahimabalde1234
      @elhadjibrahimabalde1234 หลายเดือนก่อน

      @@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.

    • @elhadjibrahimabalde1234
      @elhadjibrahimabalde1234 25 วันที่ผ่านมา

      ​@@RainerHahnekamp run the ap today and its ok

  • @johnvanleeuwen6886
    @johnvanleeuwen6886 หลายเดือนก่อน

    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 ???

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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.

  • @andyhb1970
    @andyhb1970 หลายเดือนก่อน

    Last one as its Sunday!! I didn't notice you use the export function withSomeFeature<_>() workaround with your feature however, if I create my feature without the dummy generic <_> then I still get compiles errors? I'm using @ngrx/signals, @ngrx/operators version ^18.0.2.

  • @andyhb1970
    @andyhb1970 หลายเดือนก่อน

    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
      @RainerHahnekamp หลายเดือนก่อน

      Yes

    • @andyhb1970
      @andyhb1970 หลายเดือนก่อน

      @@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 🙂

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@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.

  • @ViniciusLopesDeAlmeida
    @ViniciusLopesDeAlmeida หลายเดือนก่อน

    Another Great Vídeo!!

  • @larshanisch
    @larshanisch หลายเดือนก่อน

    Nice video! One question about withCountdown: how would you initialize timeLeft with the correct value from the parent state?

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Thanks, didn't I do that? I am using the timeInSeconds from the parent state?

    • @larshanisch
      @larshanisch หลายเดือนก่อน

      @@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.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@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...

    • @larshanisch
      @larshanisch หลายเดือนก่อน

      @@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... 🤓

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@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.

  • @scellilisa
    @scellilisa หลายเดือนก่อน

    danke, echt super wie immer!

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Merci beaucoup Lisa 😉

  • @kirilhalahan4313
    @kirilhalahan4313 หลายเดือนก่อน

    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!

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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!

    • @kirilhalahan4313
      @kirilhalahan4313 หลายเดือนก่อน

      @@RainerHahnekamp Thank you for the quick response, I will try it immediately

  • @rafajuchnicki1713
    @rafajuchnicki1713 หลายเดือนก่อน

    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?

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Unfortunately yes. If you go with github.com/timdeschryver/ngrx-immer you can also do a mutable update, though.

  • @jacqueskloster4085
    @jacqueskloster4085 หลายเดือนก่อน

    I just implemented a signal store for a part of the app where I had a full blown ngrx store before with actions, effects etc. I have to say it's very appealing especially in apps where you cannot shake the feeling that the full ngrx store is just... overkill. And boy it is overkill given the amount of boilerplate code and decentralization of coherent things happening. I also like the approach more than how component stores were setup. This is a lot more beginner friendly, uses modern angular features and just works. And you have (almost) everything in one place. For "get that api response in and let's work on the data" things that aren't overly complex by themselves, I happily dropped the full store despite its advantages regarding tracking, devtools, ... Full ngrx stores are really only necessary in apps where you have a gazillion of components and a very modular environment with many things that need to react to a change of data somewhere.

  • @AenGex
    @AenGex หลายเดือนก่อน

    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.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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.

    • @AenGex
      @AenGex หลายเดือนก่อน

      @@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?

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @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.

    • @AenGex
      @AenGex หลายเดือนก่อน

      @@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!

  • @borjaalvarez3483
    @borjaalvarez3483 หลายเดือนก่อน

    Awesome!!! 👏👏

  • @koempf
    @koempf หลายเดือนก่อน

    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!

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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.

    • @koempf
      @koempf หลายเดือนก่อน

      @@RainerHahnekamp stimmt sorry ich hab falsch geschaut :-) Steffen mal wieder ;-)

  • @staoish
    @staoish หลายเดือนก่อน

    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

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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."

    • @staoish
      @staoish หลายเดือนก่อน

      ​@@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

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@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?

    • @staoish
      @staoish หลายเดือนก่อน

      @@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

  • @davesharman8302
    @davesharman8302 หลายเดือนก่อน

    Thanks Ranier, this was a helpful video on the new features.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Thanks, you are very welcome Dave.

  • @JeffryGonzalezHt
    @JeffryGonzalezHt หลายเดือนก่อน

    Worth the wait! Fantastic work - to you and the whole team. The signalStoreFeature was the missing piece for me, and I didn't even know it. ;)

  • @rolandjost3823
    @rolandjost3823 หลายเดือนก่อน

    The best trainer. Thanks for sharing

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Thanks for your ongoing support Roland.

    • @rolandjost3823
      @rolandjost3823 หลายเดือนก่อน

      It's simply the truth. Your explanations are clear and simple.

  • @ARIAS9306
    @ARIAS9306 หลายเดือนก่อน

    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?

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      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.

    • @ARIAS9306
      @ARIAS9306 หลายเดือนก่อน

      @@RainerHahnekamp thanks for your answer 👍

    • @andyhb1970
      @andyhb1970 หลายเดือนก่อน

      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 🤔

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@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.

  • @DJpiya1
    @DJpiya1 หลายเดือนก่อน

    Another fantastic content. Awesome. Looking forward to see Spring OAuth + OpenID + Spring Session integration with SPA frontend. Thanks a lot.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Yup, that was the idea. The article has already been published several months go. The video is missing.

    • @DJpiya1
      @DJpiya1 หลายเดือนก่อน

      @RainerHahnekamp lovely, ur contents are fantastic. Please keep them coming in. 🙏🙏

  • @DJpiya1
    @DJpiya1 หลายเดือนก่อน

    Man, u r awesome 🎉😎, its surprising that this video has more than 1k views and only 47 likes. Anyway, u got a new subscriber. Thanks for this wonderful content.

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Thanks a lot. I really should do more Spring-related videos...

  • @wiliamferraciolli5380
    @wiliamferraciolli5380 หลายเดือนก่อน

    This is great, got a bit tricky at the end, but thanks a lot

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Yeah, I know. Extensibility is the most powerful feature but also the hardest.

  • @prasoon2510
    @prasoon2510 หลายเดือนก่อน

    If i need to do some operations based on signal data, how to do that in component.. Not able to do that

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Hi Prasoon, generally speaking, that's what an effect is for. Can you maybe give me a concrete example?

    • @prasoon2510
      @prasoon2510 หลายเดือนก่อน

      @@RainerHahnekamp Yes I used effect and it works.. Can we use multiple effect of same component or not??

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@prasoon2510 Yes, you can have as many effects as you want.

    • @prasoon2510
      @prasoon2510 หลายเดือนก่อน

      @@RainerHahnekamp Thank you so much for the quick response 😊❤️

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      @@prasoon2510 You are very welcome. If something is still unclear, let me know

  • @SaleemKhan17
    @SaleemKhan17 หลายเดือนก่อน

    Can you share your vscode extensions?

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Saleem, that's IntelliJ what I'm using. If you mean the inlay Hints, they are available in VSCode as well: code.visualstudio.com/docs/typescript/typescript-editing#_inlay-hints

  • @n8_may
    @n8_may หลายเดือนก่อน

    @20:16 I believe exhaustMap() should be used over switchMap(). switchMap() would restart the stream rather than ignoring subsequent ones

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      If I use an exhaustMap and switch quickly between page 2, 3 and 4, it could happen that requests for 3 and 4 are not processed. exhaustMap waits for the inner observable to complete and ignores all incoming values from the outer observable. So for pagination, you usually go with switchMap.

  • @emilsirbu236
    @emilsirbu236 หลายเดือนก่อน

    As always super valuable content, thanks Rainer! 💪

  • @lahcenaouina
    @lahcenaouina หลายเดือนก่อน

    Can please do a video explain how to manage cach (CRUD with Pagination) using ngRX

    • @RainerHahnekamp
      @RainerHahnekamp หลายเดือนก่อน

      Hey, I'm not sure if CRUD + Pagination is enough for a complete video but I can answer specific questions, if you have any. What are you struggling with? In the end you have a list of entities with the CRUD actions and additional actions to swtch pages.