Это видео недоступно.
Сожалеем об этом.

NgRx Signal Store Trilogy, Part 1: Why, When, and How?

Поделиться
HTML-код
  • Опубликовано: 14 авг 2024
  • 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 shift gears to live coding, demonstrating the practical application of the Signal Store by migrating from the NgRx Global Store.
    The true power of the Signal Store lies in its extensibility, which I'll unveil in the final segment. Witness the ease with which reusable features can be crafted, transforming your Angular development experience.
    Here is part 2 of the trilogy: • NgRx Signal Store Tril...
    The GitHub repository is available at github.com/rai....
    0:00 1. Introduction
    0:34 2. Signals - Enforced State Management?
    3:28 3. Signal Store at a Glance
    6:16 4. Using the Signal Store
    6:24 4a. Application Walkthrough
    9:15 4b. signalStore
    19:43 4c. rxMethod
    27:42 5. Architectural Aspects
    34:15 6. Why a functional approach?
    36:18 7. Extensibility
    36:20 7a. Basic Extensibility
    43:52 7b. Chained Extensions
    46:47 7c. Nested Extensions
    49:59 8. NgRx Workshops
    50:13 9. Summary & Farewell

Комментарии • 167

  • @jamesdouglaswhite
    @jamesdouglaswhite 5 месяцев назад +1

    Wow, great introduction to these amazing new functionalities! I will be signing up for more!

  • @fmaransatto
    @fmaransatto 5 месяцев назад +4

    Awesome video, my only suggestion is to adjust your microphone equalizer and make it more acute, remove the bass, it's a bit difficult to understand.

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад +3

      Thanks a lot. After that recording I bought a wireless microphone. Sorry for the bad audio quality. Will not happen again :)

    • @fmaransatto
      @fmaransatto 5 месяцев назад

      @@RainerHahnekamp It's nice to see a small channel with such a great quality and you have potential to grow. I've invested on youtube a few years ago, you can check out my channel containing angular and other nodejs content, but it's all in Portuguese. youtube.com/@fmaransatto

    • @fmaransatto
      @fmaransatto 5 месяцев назад

      @@RainerHahnekamp let me consider reproducing a similar content but in Portuguese

  • @sakarsr
    @sakarsr 6 месяцев назад

    A really great introduction to NgRx/SignalStore. Thank you for your time to put it up. I am planning to use it in my ongoing project.

  • @OlehBiblyi
    @OlehBiblyi 7 месяцев назад +5

    Great video, really unique content. Thank you!

  • @dragos.grigore
    @dragos.grigore 6 месяцев назад

    I learnt a lot of information from your video. I'll just go and apply everything now. Thank you for this full of information video, Rainer!

  • @MikeKushnerPoland
    @MikeKushnerPoland 6 месяцев назад

    Wow, great video and great intro to SignalStore & Signals. I'm jumping right into this now! Thanks!

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      You're welcome. Btw. a second one is going to be published very soon but that's a secret 🤫

  • @dhavalv
    @dhavalv 7 месяцев назад

    Rainer really good stuff. Didnt realize the encapsulation bit that I will not have with the SignalStore. Really good overview

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      Thanks a lot Dhaval. I hope that there will soon be an encapsulation feature available.

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      In the meantime, a PR is available: github.com/ngrx/platform/pull/4210. You can upvote if you are in favor of that feature.

  • @emilsirbu236
    @emilsirbu236 29 дней назад

    As always super valuable content, thanks Rainer! 💪

  • @olgoree
    @olgoree 3 месяца назад

    I really like the general approach with having the state out of the component and quite minimal with signalstore compared to that huge boilerplate code you have to write for standard state management with ngrx.

    • @RainerHahnekamp
      @RainerHahnekamp  3 месяца назад

      Yes, me too. It makes things a lot of easier.

  • @n8_may
    @n8_may 28 дней назад

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

    • @RainerHahnekamp
      @RainerHahnekamp  28 дней назад +1

      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.

  • @wiliamferraciolli5380
    @wiliamferraciolli5380 19 дней назад

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

    • @RainerHahnekamp
      @RainerHahnekamp  19 дней назад

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

  • @yanekvoloshchuk64
    @yanekvoloshchuk64 6 месяцев назад

    Amaizing content! As always. Brilliant knowledge sharing. Thanks a lot!

  • @LarsRyeJeppesen
    @LarsRyeJeppesen 4 месяца назад

    Absolutely love SignalStore.

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад

      yeah, me too (guess that's not really a surprise)

  • @DenisGitonga
    @DenisGitonga 7 месяцев назад

    Glad have discovered your channel very educative. Waiting more knowledge sharing.

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      Thanks Denis, what kind of content would you expect?

    • @nnaluekenneth8420
      @nnaluekenneth8420 Месяц назад

      ​@@RainerHahnekampI am also very happy to find your channel. I appreciate the way you explain advanced topics and I'm looking forward to more content on building systems like esbuild, and the usage of design patterns in Angular (Adapter, Composite, Facade, etc).

    • @RainerHahnekamp
      @RainerHahnekamp  Месяц назад

      @@nnaluekenneth8420 Thanks, there is a video covering the Facade in NgRx. I would also be interested to cover build systems. Not just esbuild, but how it works together with Vite and what other parts are relevant in this area.

  • @Petre66CA
    @Petre66CA 5 месяцев назад

    Still wrapping my head around using the signal store. However, the presentation is good. Thank you for sharing the code to allow for a slow digestion of information.

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      You're welcome. Is there something specific you are struggling with?

    • @Petre66CA
      @Petre66CA 5 месяцев назад

      @@RainerHahnekampI am struggling with the deluge of new terms. How is a signal different from an event emitter in earlier Angular versions?

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      @@Petre66CA The EventEmitter extends from a Subject and you should only use it for dispatching Events to be consumed by the parent component. You might want to compare a Signal to BehaviorSubject or Observable in general. I highly recommend you to read github.com/angular/angular/discussions/49684 where they explain why Signals at all and how they are different from RxJs.

    • @jamesdouglaswhite
      @jamesdouglaswhite 5 месяцев назад

      I did not know such docs existed, what a game changer. Thanks for the clue@@RainerHahnekamp

  • @arnoldm5358
    @arnoldm5358 3 месяца назад

    Hi Rainer, thanks a lot for sharing! I often use actions and effects to manage global UI state for example. Is this still possible with NgRx signalStores? Can signalStores communicate with each other?

    • @RainerHahnekamp
      @RainerHahnekamp  3 месяца назад

      Hi, thanks. So the way how SignalStore can communicate with each other is via the dependency injection. You can find in example at: github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/bookings.store.ts The bookingStore has a dependency to the customersStore.
      Reducer & Actions are part of the Redux pattern and not supported in the Signal Store. You could use our Redux extension: github.com/angular-architects/ngrx-toolkit, stick to the global store, or try to do it without Redux.
      Does that answer your question?

  • @uchto4
    @uchto4 Месяц назад

    I'm always thinking about the glitch-free-effect. What if I call a method for example twice with different inputs? Will the first one be gone?
    What if I want to use the signalstore for events . I fill a buffer with events from a websocket. Will I lose data?
    I really like the signal store, but I can't get my head around this. :o

    • @RainerHahnekamp
      @RainerHahnekamp  Месяц назад +1

      So if you call a method twice synchronously, the first one will be dropped. WebSocket messages usually arrive asynchronously, so they won't be dropped by the glitch-free effect.
      You can use the SignalStore for events with rxMethod, but you have to think what type you use to represent that event. I would avoid putting an event into as Signal, usually the events comes from an Observable or an event listener (also works without rxMethod). Observables and event listeners are both fine.
      If you end up having dependencies between signal stores, then you will very quickly have an event in the form of a Signal. You might now be worried about the glitch-free effect, but from my experience, it is very rarely a real issue.

  • @beezesty
    @beezesty 4 месяца назад

    Very nice and clear, to the point. Thanks a lot. So is this more or less the end of ngrx/store and will the community move to SignalStore for global state?

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад +1

      Thanks I can't predict 100% the future, but yes. Also the NgRx team says (talk at ng-conf) that SignalStore is the way to go. Only, if you absolutely must use the Redux pattern, then the global State is an option.

  • @meerawisniewski1351
    @meerawisniewski1351 Месяц назад

    Great example. What if my load method takes 2 more parameters they are signals? Do i need separate state for that? would my load method will call when those values changes? Currently i am using angular effects with signals and effects for loading data gets called when any of those values changes.

    • @RainerHahnekamp
      @RainerHahnekamp  Месяц назад

      Thanks. If the parameteruses is a Signal, rxMethod applies an effect to it. If it is an Observable, it subscribes to it. Every time an Observable emits or Signal emits (careful with glitch-free), the inner Observable is executed.
      To put it short for Signals: rxMethod is just a wrapper around the effect function with an untracked in it.
      Did I answer your questions?

  • @miklosbecsei8128
    @miklosbecsei8128 6 месяцев назад

    This is is amazing! Thanks for the video!

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      You are welcome. Btw, it has been released in 17.1 this week.

  • @loko1944
    @loko1944 7 месяцев назад +12

    awesome content, but terrible audio :/

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +1

      Hi, how bad is it? Do you think it is better, if I do a retake?

    • @loko1944
      @loko1944 7 месяцев назад +1

      ​@@RainerHahnekamp Hi. Its really bad, but I always payed a lot of attention to this so maybe other people wont be bothered so much. I treated video as nice introduction, but skipped some parts and filled gaps with articles due to this.

    • @hille-hausonfire4338
      @hille-hausonfire4338 7 месяцев назад +3

      @@RainerHahnekamp Yes, the sound quality is not particularly good, but I don't mind. I appreciate much more the hard work put into the video and the valuable information, so the sound quality doesn't really matter. Thanks for the great video Rainer! I hope you had a wonderful Christmas. Wishing you all the best for the New Year and hope you continue to give us such good content :)

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +2

      @@hille-hausonfire4338 Thanks both. I will manually create subtitles and will upload them. The automatic ones aren't that good. To me, it is important that you can understand what I'm saying. As soon as that's not the case anymore, I have to re-record it. And thanks for Christmas wishes. Hope you enjoyed it as well!

  • @ramoo06
    @ramoo06 6 месяцев назад

    Great content.
    Thank you so much.

  • @maciek77killer
    @maciek77killer 3 месяца назад

    Can I combine stores? For example, to retrieve all products of the logged in user?

    • @RainerHahnekamp
      @RainerHahnekamp  3 месяца назад

      Sure, the bookingStore for example has a dependency to customersStore: github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/bookings.store.ts.
      You just inject whatever you require, and that should do it.

  • @davesharman8302
    @davesharman8302 2 месяца назад

    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  2 месяца назад

      --legacy-peer-deps is the recommended option. See here: github.com/ngrx/platform/issues/4352

    • @davesharman8302
      @davesharman8302 2 месяца назад

      @@RainerHahnekamp Perfect, thanks for the reply. I have been greatly enjoying your videos on signals and the signal store.

    • @RainerHahnekamp
      @RainerHahnekamp  2 месяца назад

      @@davesharman8302 Thanks Dave. Happy to hear that 😄

  • @SonPham-zy2zp
    @SonPham-zy2zp 3 месяца назад

    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  3 месяца назад

      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 3 месяца назад

      @@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  3 месяца назад

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

  • @rajeshnakrani526
    @rajeshnakrani526 6 месяцев назад

    Always appreciate your videos! I adopted the not-loaded, loading and loaded paradigm from watching your videos as I was learning about state management in Angular.
    I had a few thoughts that I wanted to share:
    - The auto-suggestion feature in the IDE you are using makes it difficult to follow along. As a viewer, we are watching and the code suggestions appear and then disappear and it forces some viewers to have to scratch their head, pause the video, backtrack and watch a section over and over. Disabling it in the IDE when making videos should make it much easier for all viewers, not just experienced developers and/or those who are familiar with the IDE you are using, to follow along.
    - I have only watched about the first half of this video, but I know that I would really love to see an example from scratch that covers managing state client-side and how to handle effects. Do we first update the state client-side and then make an external call (to an api)? Is it possible (and is it a good architecture) to use the NOT_LOADED, LOADING and LOADED paradigm that was used previously in the rxjs variant of NgRx?
    Thanks again, much appreciated, you offer really good thoughts about architecture and design!
    - raj

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      Hi Raj, thanks a lot for your comments.
      I'm not sure I understand your point about the IDE auto-suggestions. Could you maybe give me an example from the video? If it helps I can of course disable whatever feature I'm using there.
      You can change the state first and then do the backen call. That's what we call optimistic locking. It brings better user experience but makes it harder for you. You always have to provide a function which reverts the state change if something goes wrong.
      It only makes sense for simple changes. If a single action triggers changes in different entities, it is way more difficult to provide a revert logic, so we usually want to send the request there first and wait for the response before updating the state.
      I would definitely recommend to use the LoadStatus pattern which I presented in one of my videos for the global store. Definitely do that!
      All the best,
      Rainer

  • @koern82
    @koern82 6 месяцев назад

    Great Video - asking myself why you don't have more subscribers.

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      Thanks, I'm quite satisfied with the current progress of my channel. I am getting more and more subscribers each day. Would have never thought that I reach 1,000 but I'm almost at 3 now. I think it is just a question of time and consistency.

    • @koern82
      @koern82 6 месяцев назад +1

      @@RainerHahnekamp with such good content, you will grow quickly. i will be visiting more often now.

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      @@koern82Thank you, if you want you can also help me by recommending this channel to your peers. 😀😅

  • @arnoldm5358
    @arnoldm5358 3 месяца назад

    Hi Rainer! Thanks a lot for sharing this knowledge! Just a question... How can the signalStores communicate with each other ? I often use effects and actions between several stores to manage the global state of applications... Is this still possible?

    • @RainerHahnekamp
      @RainerHahnekamp  3 месяца назад

      Hey Arnold, I have already answered your question below. I think you asked twice :)

    • @arnoldm5358
      @arnoldm5358 3 месяца назад

      @@RainerHahnekamp Sorry Rainer! My first comment didn't show up when I submitted it, so I wrote another one. 😅

    • @RainerHahnekamp
      @RainerHahnekamp  3 месяца назад

      @@arnoldm5358I see, all good!

  • @etexalbania7301
    @etexalbania7301 2 месяца назад

    thank you for the video, a question about testing, why haven't you done a video for angular testing with Selenium?

    • @RainerHahnekamp
      @RainerHahnekamp  2 месяца назад +1

      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 2 месяца назад

      @@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  2 месяца назад +1

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

  • @walterluszczyk
    @walterluszczyk 4 месяца назад

    Hi, thanks for grat tutorial. Furthermore. do you have any material which shows how to manage with saving data to DB?

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад

      Hi Walter, you are welcome. Do you mean Date or data?

    • @walterluszczyk
      @walterluszczyk 4 месяца назад

      @@RainerHahnekamp sorry for the typo, I meant "data". I considered for example such as restaurant rating. It is quite simple to define a state (rest. name, photo, rating, etc.), load it at the beginning and show the state in template. But what should happen when user is rating restaurant by clicking 4th star? Should store be somehow involved in passing data (vie REST) to server? Or should I update data in store and in database separately?

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад +1

      @@walterluszczyk Yes, the store is responsible for calling the backend. Instead of patchState, the store would have a method called 'updateRating'. In that method, the store calls the API and then updates the store via patchState.

  • @andyhb1970
    @andyhb1970 6 месяцев назад

    Hi Rainer, when patching state in the store if you have nested objects once you go to the second level object you must supply all parameters not just the attributes that have changed, is this a limitation of the patch state concept?

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      Yes, exaclty. So the patchState refers only to the first level. A possible alternative might be patchState(store.nestedProperty, {foo: 1}) but that does not exist.

    • @andyhb1970
      @andyhb1970 6 месяцев назад +1

      @@RainerHahnekamp interesting I see there's a similar issue raised in the component store on gh. Thanks for the feedback

  • @andyhb1970
    @andyhb1970 6 месяцев назад

    Hi Rainer, another challenge I have encountered is how do you initiate a method call on a component signalStore via a signal state change in a global signalStore? My scenario has a CompanyId on the global signalStore which can be changed by the user at any given point, there are then a collection of chart components which needed to be refreshed but I can't work out how I would do that other than using an effect which firstly causes a problem because by default you can't change signal states within them and I don't want to override that behaviour it suggests I'm doing something wrong!

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      Hi, you do that via rxMethod. rxMethod would trigger a method of a local signalStore whenever the the selector/signal of the companyId changes.
      Do you have some code snippt, so that I get a better impression on what you do?

    • @andyhb1970
      @andyhb1970 6 месяцев назад

      I have my rxMethod that loads the chart data and I call that on the ngOnInit of the chart component and the data loads however, how do I call that method again when the CompanyId changes externally?@@RainerHahnekamp

    • @andyhb1970
      @andyhb1970 6 месяцев назад

      @@RainerHahnekamp not sure what happened I responded to this an hour ago and now it's disappeared! Anyhow, I've got a solution working by converting my authStore.companId signal to an observable and subscribing to that in my component constructor e.g.
      this.companIdChangedSubscription = toObservable(
      this.authStore.companyId,
      )
      .pipe(tap(() => this.loadChartData()))
      .subscribe();
      However, I thought I'd seen the back of subscribing and unsubscribing, or is there another way?

    • @andyhb1970
      @andyhb1970 6 месяцев назад

      @@RainerHahnekamp I keep replying and my reply just disappears :-(

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      @@andyhb1970 then write to me directly on LinkedIn or Twitter please

  • @sawmkcsaw
    @sawmkcsaw 7 месяцев назад

    In component store can create selector something like storeBSomeValue$ = this.select(this.#storeA.someValue$, (someValue) => someValue). Is it possible to provide state from other store? So I can get access to value from storeA using storeB. Thank you for nice video.

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +1

      Sure, I've pushed a version which contains a bookingStore that requires data from the customersStore. Check it out here: github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/bookings.store.ts

  • @user-lc1wi4il9r
    @user-lc1wi4il9r 6 месяцев назад

    Hi, thank you for the content
    I would like to ask if we can use store methods inside rxMehtod?
    For example, if I need to implement a search and in case of an empty query, just call the loadAll() method, how can I access it from inside rxMethod?

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      Hi, can you give me a more concrete code example? You have direct access to your store in an rxMethod. So it shouldn't be an obstacle, but I think you asking for something more specific.

    • @user-lc1wi4il9r
      @user-lc1wi4il9r 6 месяцев назад

      @@RainerHahnekamp
      *RUclips is deleting my comment for some reason
      I'll split it into two parts
      Yes, you are right, I have access to store inside rxMethod, but it is access to its properties that are declared in initialState. I don't have access to the methods themselves. Here is a simple code sample where you can see what the problem is:
      const initialState: IUsersState = {
      users: [],
      isLoading: false,
      error: null,
      }
      export const usersStore = signalStore(
      { providedIn: 'root' },
      withState(initialState),
      withMethods((store) => ({
      generateUsers() {
      return [ { name: 'John' }, { name: 'Marry' } ];
      },
      loadAll() {
      const users = this.generateUsers();
      patchState(store, { users });
      },
      search: rxMethod(
      pipe(
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((query) => {
      if (!query) {
      this.loadAll(); // TS2532: Object 'this' is possibly undefined
      //OR
      store.loadAll(); // TS2339: Property loadAll does not exist on type
      // {
      // users: Signal;
      // isLoading: Signal;
      // error: Signal;
      // [ STATE_SIGNAL ]
      // :
      // WritableSignal;
      // }
      }
      // ...rest of code
      }),
      ),
      ),
      })),
      );

    • @user-lc1wi4il9r
      @user-lc1wi4il9r 6 месяцев назад

      As you can see, I have no problem accessing generateUsers() inside loadUsers() via 'this'.
      But in rxMethod the context is lost, so this.loadAll() displays an error because 'this' === undefined.
      Also when using store.loadAll() inside rxMethod I get an error that such a method does not exist on my store type (but still I have an access to 'users', 'isLoaing' and 'error').
      Now I've found a solution that looks something like this:
      export const usersStore = signalStore(
      { providedIn: 'root' },
      withState(initialState),
      withMethods((store) => {
      function generateUsers() {
      return [ { name: 'John' }, { name: 'Marry' } ];
      }
      function loadAll() {
      const users = generateUsers();
      patchState(store, { users });
      }
      const search = rxMethod(
      pipe(
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((query) => {
      if (!query) {
      loadAll();
      }
      // ...rest of code
      }),
      ),
      );
      return { loadAll, search };
      }));
      I hope my explanation is clear😅

  • @alexle7895
    @alexle7895 6 месяцев назад

    I enjoyed the video very much, but I wish the audio could be better. I turned my volume to 100% and it was still difficult to hear.

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      Hello Alex, sorry for the poor quality. It was due to a damaged wire of the microphone and I had to aggressively apply audio filters to remove the majority of the background noise.
      It won't happen again. Switched now to a wireless microphone.
      You can also watch the second Part which takes on a different perspective but with much better audio quality.

  • @tonyxavier4724
    @tonyxavier4724 5 месяцев назад

    Which font and theme are you using in this ?

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      The font is cascadia code pl but the rest is standard IntelliJ

  • @user-qf8wm5nn1i
    @user-qf8wm5nn1i 6 месяцев назад

    Great video. Thank you for the amazing content. I am wondering how to update the store based on a signal input of the component. Let's assume having an input "id". Whenever the "id" changes I would like to update the store. How would this be done?

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      Hi Lukas, that’s where you use rxMethod. If you have an rxMethod of type number for example, it doesn’t just accept a number as parameter but also a signal of oberservable of type number. You can an example here: github.com/rainerhahnekamp/eternal/blob/talk/ng-india-2024-solution/src/app/holidays/feature/quiz/quiz.component.ts

    • @user-qf8wm5nn1i
      @user-qf8wm5nn1i 5 месяцев назад

      Thank you for the fast reply. I really appreciate it.
      Makes sense. That’s how I did it in the end anyway. I was just not sure if it is the best way to do it as I initially thought rxMethod is only necessary working with rxjs. In this case the only operator needed is tap to patch the state. But it works fine. 👍🏻
      Originally I used an effect within the component but this resolved in some errors. I just wanted to mention it if someone else also experiences this “problem”.
      Anyway. Thanks for the response and the great content. Keep it going. ✌🏻☺️

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      @@user-qf8wm5nn1i Thanks, I will 💪👍

  • @usmanmustafa6845
    @usmanmustafa6845 7 месяцев назад +1

    if possible , can you please shared repo link ?

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +1

      Sure, there you go: github.com/rainerhahnekamp/ngrx-signal-store-demo

  • @mobilelegendprabumulih6873
    @mobilelegendprabumulih6873 6 месяцев назад

    YOUR CROWN HAS FALLEN, KING 👑👑

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      It falls slowly but it the crown stays within the dynasty

  • @vutruong4164
    @vutruong4164 7 месяцев назад

    great intro to SignalStore. It really looks more intuitive and yet equally powerful (if not more) than the original global store/ComponentStore.
    Do you know if the effect() API will be introduced to SignalStore once effect() is fully stable, for example, withEffects()? The current approach, withMethods + rxMethod seem not fully "signalized" to me, but I do think it is sufficient for almost all use cases

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +1

      I don't think so. The rxMethod itself also expects a signal and is executed whenever that Signal emits. In that sense, rxMethod is already an effect.

    • @vutruong4164
      @vutruong4164 6 месяцев назад

      Thanks. I read up the documentation on SignalStore on NgRx and realized that the function generated by RxMethod can actually receive a static value (effect triggers only once), and a signal/observable (effect triggers on signal/observable update), and it auto-cleanup since it got access to DestroyRef in InjectionContext. Way more powerful than I initially thought.
      I look forwards to future videos on this very interesting SignalStore, perhaps on a higher architectural level, such as using it as global store, connecting and initializing component-level signalStore to global signalStore

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      @@vutruong4164 Yes, there is an upcoming video where I focus more on the role of the Signal Store to enhance Angular's Signals. I'll explain the rxEffect there more in detail.
      When it comes to global and local store, the repo of this video contains already a working example. github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/bookings.store.ts. You just inject like any other store.

    • @vutruong4164
      @vutruong4164 6 месяцев назад

      @@RainerHahnekamp sorry for troubling you again, but is there still the concept of eagerly vs lazily initialing states with SignalStore?
      My understanding is withState will always eagerly initialize the store, so I probably have to initialize states with "undefined" if I want to "lazily" initialize states later by using a load method in withMethods

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      ​@@vutruong4164No worries at all. So as soon as you inject the Store for the first time, it will be initialized and it has to have state from the very beginning. You could use undefined, but I would provide default values and a property to my state that says if the state is ready or not. If you use undefined for all your properties, you always have those union types which are net very comfortable to work with. All components, all services have to deal with those.

  • @prasoon2510
    @prasoon2510 27 дней назад

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

    • @RainerHahnekamp
      @RainerHahnekamp  26 дней назад

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

    • @prasoon2510
      @prasoon2510 26 дней назад

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

    • @RainerHahnekamp
      @RainerHahnekamp  26 дней назад

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

    • @prasoon2510
      @prasoon2510 26 дней назад

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

    • @RainerHahnekamp
      @RainerHahnekamp  25 дней назад

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

  • @andyhb1970
    @andyhb1970 7 месяцев назад

    Thanks for the video, how can you update multiple states let's say you have a component scoped state but you also want to update part of the global application state, with actions and reducers you can hook onto any action you wish and thus reduce multiple states, but I can't see how you would do that with Signal Store?

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      You would require to have access to the component-provided and to the global state. patchState will work for both. Did you mean that?

    • @andyhb1970
      @andyhb1970 7 месяцев назад

      @RainerHahnekamp Yes but how do I provide access to both states, how do I provide that access, is it via the withMethods parameter list? if so how do I get the store instance to pass through?

    • @andyhb1970
      @andyhb1970 7 месяцев назад

      @@RainerHahnekamp I think I've solved it, by exporting the type from my store e.g. "export type AuthStore = InstanceType;" I can then pass it into the withMethods function and use it with patchState! Not tested it yet though 🙂

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +1

      ​@@andyhb1970That sounds a little bit unnecessary. If you want in your withMethod access to another store, then just use the inject function. You can an example here: github.com/rainerhahnekamp/ngrx-signal-store-demo/blob/main/src/app/bookings.store.ts

    • @andyhb1970
      @andyhb1970 7 месяцев назад

      @@RainerHahnekamp I've just removed the exported type and it's working fine! I must have had a funny five minutes or VS Code intellisense did!!! Yes you're right I can just inject any dependencies into the withMethods function.

  • @TheHelianos
    @TheHelianos 7 месяцев назад

    there is a solution to easily handle side effects with it ??
    I have a case that one slice of a store, when updated, trigger a side effect in another slice to handle... it's like a domain event.

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      Yes there is. The function you generate with rxMethod can also accept an Observable or event a Signal.
      Example:
      const Store = signalStore(withMethods(store ({incrementer: rxMethod()})));
      const store = new Store();
      // default usage
      store.incrementer(1);
      // usage with Observable
      store.incrementer(of(1,2,3));
      //usage with Signal
      const number = signal(1);
      store.incrementer(number);
      ---
      So you just provide your event in the form of an Observable and you're done.

    • @TheHelianos
      @TheHelianos 7 месяцев назад

      @@RainerHahnekamp thank you... it helped a lot!

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      @@TheHelianos You are welcome. That rxMethod is extremely powerful. Also outside of the Signal Store. RxJs v8 will have something similar built-in

  • @MahmoudTarek-pz1rl
    @MahmoudTarek-pz1rl 6 месяцев назад

    Can I use it now in my upcoming projects or it is still not stable?

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      You can use it. It is very stable.

    • @MahmoudTarek-pz1rl
      @MahmoudTarek-pz1rl 6 месяцев назад

      @RainerHahnekamp Thanks a lot, and thank you so much for the great content.
      I wish to see and learn more about new approaches

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад +1

      ​@@MahmoudTarek-pz1rl You're welcome. I wouldn't expect that the SignalStore will get so many new features. Maybe some extensions like withEntities but not in its core.

    • @MahmoudTarek-pz1rl
      @MahmoudTarek-pz1rl 6 месяцев назад

      @RainerHahnekamp I totally agree with you.
      But I was sure that something related to deal with entities will have a place with signal store, whatever how.
      But, for me the surprise and it was the first time I see it I even didn't came across it was signalStoreFeature it is really powerful feature to have, extensibility in this way and having a generic store features just so much powerful

  • @jdnichollsc
    @jdnichollsc 7 месяцев назад +1

    First question, are Signals ready for Production? 😅

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад +4

      signal() & computed(): yes (since Angular 17)
      effect(): no (developer preview)
      NgRx Signal Store: no (developer preview)
      I'd like to add that developer preview does not mean that it is untested and you to expect bugs, like in a beta version. Developer Preview means it is quite stable but they can introduce breaking changes within a major version.

    • @jdnichollsc
      @jdnichollsc 6 месяцев назад

      @@RainerHahnekamp awesome, still waiting for a stable version of that NgRx Signal Store, thanks for sharing!

  • @donwald3436
    @donwald3436 2 месяца назад

    huh signals replace ngrx tho?

    • @RainerHahnekamp
      @RainerHahnekamp  2 месяца назад

      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.

  • @Marc-ox7fy
    @Marc-ox7fy 5 месяцев назад

    Do you have Dutch ancestors? Hahnekamp/Hanenkamp, it is a Dutch name.

    • @RainerHahnekamp
      @RainerHahnekamp  5 месяцев назад

      Yeah, I know. I come from a small village in East Austria where half of the population have that surname. What I know from ancestry research is that one Hahnekamp appeared there in the 17th century. I guess Hahnekamp got a little bit germanized. The "kamp" is still as it was but I don't think that "Hahne" is Dutch.

  • @floriss9
    @floriss9 4 месяца назад

    I'm having trouble understanding you because of the audio quality

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад

      Sorry, I am aware of that and all my newer videos are using a much better microphone. You can also checkout the second part which has overlapping content with that one.

    • @floriss9
      @floriss9 4 месяца назад

      @@RainerHahnekamp Nice! Thanks for that. Good luck and keep up the good vids

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад

      @@floriss9Thanks, will do!

  • @birdvoron
    @birdvoron 7 месяцев назад

    very good stuff. But where is github? ;-)

    • @RainerHahnekamp
      @RainerHahnekamp  7 месяцев назад

      Thanks! Here it is: github.com/rainerhahnekamp/ngrx-signal-store-demo

  • @AndrejMilas
    @AndrejMilas 7 месяцев назад +2

    Ngrx all ur angular state are belong to us

  • @ShaggyRobot
    @ShaggyRobot 4 месяца назад

    Please, consider better mic or equalization in post, your audio is too bassy, it is not good for voice clarity.

    • @RainerHahnekamp
      @RainerHahnekamp  4 месяца назад

      Hi, I've considered it already after that recording ;) All my newer videos are now done with a wireless mic. If you checkout the second part, you should hear that it is much better.
      I still hope, you could understand what I said.

    • @ShaggyRobot
      @ShaggyRobot 4 месяца назад

      That's great :) @@RainerHahnekamp

  • @VladiSecuritas
    @VladiSecuritas 2 месяца назад

    voice sound quality is really bad.. please use a proper mic.

    • @RainerHahnekamp
      @RainerHahnekamp  2 месяца назад

      Yes sir, threw it away after that one and working with a wireless. You can see the difference in the second part.

  • @cocoscacao6102
    @cocoscacao6102 6 месяцев назад

    Still hilariously overcomplicated way to achieve something a simple service can do....

    • @RainerHahnekamp
      @RainerHahnekamp  6 месяцев назад

      Well, the SignalStore is still in developer preview. If you can provide an easier solution with the same kind of extensibility, we will be more than thankful.