NgRx Best Practices - Episode 3: Routing & other Deferrals

Поділитися
Вставка
  • Опубліковано 13 жов 2024

КОМЕНТАРІ • 38

  • @aram5642
    @aram5642 2 роки тому +1

    Missing your videos in this series, a lot!

  • @borjaalvarez3483
    @borjaalvarez3483 8 місяців тому

    Hey, just landed into your videos and they are awesome! Just learning Ngrx and I have a doubt about your video. In the loader spinner part, is better the callback function or should I save the loading property as part of the state?? Thanks and regards!

    • @RainerHahnekamp
      @RainerHahnekamp  8 місяців тому +1

      Yeah, always a good to question things you see in videos and then ask for clarification 👍.
      So the basic usage of the store in this use case is that the state is generic and completely decoupled from the UI. That means, multiple components can update or add a new entity. So we would have to extend our state for loading indicators for every component out there, like `{loadingStatusForAddComponent: boolean, loadingStatusForQuickAdd: boolean, loadingStatusForOverview: boolean}`. Because of the decoupling we need to find another way.
      If, on the other side, you decide that it completely find that your state is aware of the components which are using it. In fact, the state is controlling the UI Components themselves, then it would realy be that I would have these additional properties per every component in my state.

  • @digitech1241
    @digitech1241 2 роки тому +1

    Very nice . Thank you.

  • @jean-yvespelletier5505
    @jean-yvespelletier5505 9 місяців тому +1

    Thanks Rainer!!

  • @jamesbarrow
    @jamesbarrow 11 місяців тому

    I was wondering about NgRx practices, and wondered if there should be a constraint that actions are immutable and serializable, and wondered if the forward factory and callback approach really applies to that? In the past I've used selectors for the loading indicator and kept that as part of the state managed by effects but it always felt like it was a component/container view or use case specific thing and that effects really shouldn't be doing that logic. The action and factory approach seems nice I just wonder if it could be over used by developers

    • @RainerHahnekamp
      @RainerHahnekamp  11 місяців тому +1

      Hi James, I see this as a compromise and not something I would apply be default. So it is a pattern you only use when your component needs to react to an internal NgRx action.
      There is actuall a runtime check (in dev mode) where NgRx checks the actions for immutability. In our case, the payload are functions, so that's fine.

  • @michaelbe6943
    @michaelbe6943 2 роки тому +1

    great content

  • @heyjude4279
    @heyjude4279 Рік тому

    Very nice video as always. I saw a snippet of the code from the video from time 2:25; verifycustomer part. VerifyCustomer function seems to be working similar to filter operator but I haven't seen this kind of example with "is Customer" inheritance part in TypeScript. How the customerGuard working?

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому

      Hi, that's a type predicate. You can find a detailed explanation in my other video: ua-cam.com/video/MUJBT3Pb_Eg/v-deo.html

  • @robertbryan6485
    @robertbryan6485 2 роки тому

    Hey Rainer, thank you for the video!
    Are you still planning on doing an episode about facades?

    • @RainerHahnekamp
      @RainerHahnekamp  2 роки тому

      Yes, but there are still three videos I have to do before (not about ngrx best practices though)

  • @regedam7559
    @regedam7559 Рік тому

    Hello, I'm reading the 'NgRx Best Practices' series posts on your site. I read the 2nd post about Modularity and found that the third part is missing, but there is a 4th part about Facade Pattern. Can you tell me if the third part of the NgRx Best Practices series exists in text format?

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому +1

      Hi, yes that's kind of awkward, isn't it 😅. I should definitely come up with a written version. I definitely have a draft because I needed a template for this video.
      So stay tuned and thanks for the reminder 👍

    • @regedam7559
      @regedam7559 Рік тому

      @@RainerHahnekamp Anyway, I'll also check out this playlist. Thanks for your work, all the information is interesting and very useful!

  • @tony-go-code
    @tony-go-code 2 роки тому

    Thank you very much

  • @Karackal
    @Karackal 2 роки тому

    Having to thread additional metadata about what has to happen afterwards always makes me feel like I'm fighting ngrx instead of using it. I get the impression that showing some kind of progress indicator and redirecting the user once data is available is something ngrx is not designed to do; or at least it isn't designed with that specific usecase in mind. This is a simple requirement with a way too complex solution in my humble eyes.

    • @RainerHahnekamp
      @RainerHahnekamp  2 роки тому +1

      Yeah, so NgRx's design is that your components shouldn't have to know when an action is "finished". The definition of finished becomes more complicated when an action triggers a complete chain of other actions...
      As I mentioned, there are alternative approaches like the one I presented. For example, injecting the actions$ into a component is something that is quite common.
      But when you value encapsulation and want to hide as much as possible, that's an absolute no-go and it also feels a little bit hacky.
      Under these conditions, going with a callback packed into an action is the best option I have seen so far.
      Nevertheless, I am absolutely on your side. It shouldn't be that hard.

  • @adiscivgin745
    @adiscivgin745 Рік тому

    Hello everyone, can someone please explain how we can get id in addCustomer$ effect. It supposed to recieve only customer as param from component and id is probably generated by backend. Am I missing something here? Thanks

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому +1

      Hi, so maybe I can explain it.
      The action has a callback function (forwardSupplier) that gets the id but of course - as you said - it can only be called after the backend generated the customer and responded. The Effect takes the id out of the response and calls the action's forwardSupplier by passing on that id.
      You can also see, that I only have access to the id after the http.post was sent. Not before. That would not be possible.

  • @jacqueskloster4085
    @jacqueskloster4085 Рік тому

    17:50 Shouldn't the control of the loading spinner rather also cleanly follow ngrx principles and use a selector that is based on a status in the store (e. g. SAVING)? Adding callbacks to actions seems rather odd to me. It seems like here you circumvent ngrx and effects just for convenience.
    In my app I solved the display of the global loading spinner by providing actions that allow consumers to add or remove "loading claims" so the app knows when at least one consumer is not display ready.
    Yes, sometimes this is cumbersome since you might have additional effects for the same action that handle the add/remove of load claims, as they need to be an action emitted by an effect that is based on another action (e. g. load and load success / load error) but at least it follows the same principles and it removes responsibility of it from the components. I know I said global loading spinner but even if it's just a spinner for a single component, it should be displayed based on ui state I think.

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому

      Hi Jacques,
      thanks for pointing that out. I was waiting for such a comment :)
      There are two different types of state. Entity and UI State. With an entity state, you want that your state is decoupled from the view. It should be as generic as possible. You can even compare it with a REST API that has no clue about the UI that uses it. That's why I also came up with strict decoupling between the data and the ui module in my video about architecture: ua-cam.com/video/B_-bH6gSpqU/v-deo.html. As a matter of fact, the most state types, we see in enterprise applications are entity-based.
      That's why UI-specific context has to be completely removed from ngrx. This goes even against some rules that we find in ui state. Like not having not having selectors for ViewModels. Instead they are generated in the container components. Or action hygiene where you create a separate action for every component it is used, even when it does the same thing.
      Coming back to the loading spinner. This is a component-specific side effect. Maybe another component is shown somewhere else that also allows an update of that entity? Should now both components start to show their loading spinner? Probably not. Should the state come up with two loading properties? No, because it shouldn't now how many components actually trigger the save action.
      Does that make sense to you? I've been thinking for some time now to come up with a video explaining the differences and their consequences.
      All the best,
      Rainer

    • @jacqueskloster4085
      @jacqueskloster4085 Рік тому +1

      @@RainerHahnekamp so I passed the test? 😄

    • @jacqueskloster4085
      @jacqueskloster4085 Рік тому

      @@RainerHahnekamp sorry I first missed that I could expand your answer and it was indeed very detailed.
      I moved to ngrx component store for local store. I agree that a per component spinner should probably not pollute the Global store. In my example, it's a Global spinner that is an overlay over the entire site. Since it's App wide, I put it in the App store and gave it actions. It's currently used for the bootstrapping process only.
      I like ngrx component store a lot as it follows similar rules of the App store and thus Provides access to local data with known patterns, although it's not 100% the same mechanism.
      Kind regards
      Jacques

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому

      ​@@jacqueskloster4085 I see, so I deal with that particular use case (global loader spinner) without state. I use an HttpInterceptor and every service can opt-out via the HttpContext.
      Component store is a great thing but I really miss the support for the Redux DevTools.

    • @GabrieleCampi
      @GabrieleCampi Рік тому

      @@RainerHahnekamp I was about to write the same as @jacqueskloster4085. I'm not sure it is correct and a good practice to pass functions or callbacks as actions props. What would happen if the callback is called after the component is destroyed? (nothing prevents the user to navigate to another route while the http call is in progress inside the effect). Also would this approach work with onPush change detection?

  • @josepalacid
    @josepalacid Рік тому

    Why don't use ngxs? Easier, more "angular way" : decorators, dependency injection, no need for "side effects". Why so many efforts on an "adapted" library when there's one native and consistent, ...and less boiler code!

    • @RainerHahnekamp
      @RainerHahnekamp  Рік тому +1

      Hi Josep,
      you should not think of NgRx as adapted library that doesn't belong to to Angular. The Redux documentation explains very detailed the underlying rules like the need for explicit side effects/middleware or why your reducer must be a synchronous function and immediately return a state.
      The reducer is the only place where the state can be changed and it should be easy to understand. That's one of the main principles. So they avoid any risks that might add complexity, like asynchrony or side effects. Following that logic, there is no "angular way" in that sense.
      When it comes to the middleware, namely to the effects, Angular is all over the place: @Injectable, DI, RxJs.
      You should also take into consideration that the NgRx has improved the developer experience also quite a bit. createFeature, createActionGroup, provideState are all features that significantly decrease the amount of code you have to write.
      Here's the Redux documentationi I've mentioned above: redux.js.org/tutorials/essentials/part-2-app-structure#rules-of-reducers
      Let me know what you think. I'm interested to hear your opinion on that.

    • @josepalacid
      @josepalacid Рік тому

      @@RainerHahnekamp I've been using NgRx until frustration. Maybe it has resolved many of the caveats and reduced boilerplate code but, when I was introduced to NGXS (FireBase and Design Course reviews, no Angular related channels ever mentioned it) I was so happily impressed with it that I promised myself never go NgRx again.
      I have no vincles with NGXS or team members, other than being profoundly grateful to some advanced users who kindly, and beyond any expectation or reward, helped me SO MUCH rewriting parts of the code and guided me to the new reactive mental model of NGXS state management.
      NGRX started indeed, as a "ported" library from React state management way. Maybe it gained better integration to Angular since then, but it will ever be compatibility linked to that paradigm and, no complaints, very useful for those who are used to it. Kudos for the maintaining team, as it can't be any other way.
      But why do you think state management tools pool of users is a zero sum game? Why can't any Angular team related or approved channel, publish a NGXS honest review? Or even a comparison where NGRX could result the winner?
      As for the information I have been able to get, (and I have a lot of higher priority tasks and deals than keeping me updated with state management libraries) NGXS has been neglected by the Angular community leaders. Maybe it's due to an absolute lack of collaboration from NGXS team with the Angular community, or they had been asking for abusive comebacks, I'll never know.
      But what's absolutely pragmatic, objective and free of marketing and political questions is the ease, speed, lightness and low learning curve of NGXS.
      And for us, barefoot coders, it's a pity and a shame that such a tool has been digged for reasons other than quality and reliability, independently of who to blame, that I don't care at all.