A Redux-like Pattern for Managing State with Angular signals

Поділитися
Вставка
  • Опубліковано 16 лип 2024
  • Now that Angular signals have been out for a while, there are patterns emerging.
    In this video, we'll walk through one such pattern for managing state with signals. This Redux-like pattern leverages the best of signals and RxJS.
    Links
    Code: stackblitz.com/~/edit/rxjs-si...
    UA-cam video: "switchMap vs concatMap vs mergeMap": • switchMap vs concatMap...
    UA-cam video: "Unsubscribe with takeUntilDestroyed": • Use takeUntilDestroyed...
    UA-cam video: "Understanding Immutablity in JavaScript": • Understanding Immutabi...
    Josh Morony's UA-cam video: "Here's what I've figured out about Angular signals" which also covers a pattern based on Redux: • Here's what I've figur...
    Josh Morony's Article: "A New Reactive And Declarative Approach to Angular State Management": modernangular.com/articles/st...
    Special Thanks
    🌟 To Jason Warner for an early code review.
    🌟 To Freddy Montes for reviewing the code prior to publication.
    🌟 To Sander Elias for a deep dive into potential enhancements to this pattern. Follow him at: mastodon.social/@sanderelias
    Content
    00:00 Redux-like pattern
    00:20 Sample application
    01:38 Define the state
    02:23 Set the initial state
    03:09 Define the selectors
    04:16 Identify the actions
    04:56 Define a Subject
    05:55 Creating the Observable pipeline
    08:59 Defining reducers
    12:30 Accessing state from the component
    12:48 Kicking off actions from the component
    13:35 Following the pattern (again)
    16:13 Modifying the component
    17:13 Wrap up
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    😊About Me
    Hey! I'm Deborah Kurata
    I'm a software developer and UA-cam content creator. I speak at conferences such as VSLive and ng-conf. I write articles for freeCodeCamp. And I'm a Pluralsight author with courses in the top 10 most popular (out of 7,000+) for over 5 years. For my work in support of software developers, I've been recognized with the Microsoft Most Valuable Professional (MVP) award, and I'm a Google Developer Expert (GDE).
    View my UA-cam content: / @deborah_kurata
    Contact me on Twitter: / deborahkurata
    Find my Pluralsight courses: www.pluralsight.com/profile/a...
    Access my freeCodeCamp articles: www.freecodecamp.org/news/aut...
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    #angular
    #angularsignals
    #angularstatemanagementwithsignals
    #rxjs
    #rxjsandsignals
    #signalsandrxjs
    #angularstatemanagement
    #angulartutorials
    #statemanagement
    #angularwithredux
    #angularstatemanagementtutorial
    #angularforbeginners
    #statemanagementinangular
    #angularredux
    #angularstatemanagementbestpractices
  • Наука та технологія

КОМЕНТАРІ • 92

  • @DiogoFaFab
    @DiogoFaFab День тому +1

    Your channel is a hidden gem! I love how you explain Angular. Thanks a lot for sharing such valuable content!

    • @deborah_kurata
      @deborah_kurata  14 годин тому

      That is so kind of you to say. Thank you! 😊

  • @advance5189
    @advance5189 22 дні тому +3

    Marvelous! You know I’m so thrilled that I came across your channel. I’m sure you help many devs to refresh previous knowledge and polish up our skills. Keep it up!

  • @ythalorossy
    @ythalorossy 4 години тому

    It is amazing.... I was doing something similar without thinking about patterns.
    I need to review all my code and adjust to this pattern.

  • @turboheadcrab666
    @turboheadcrab666 19 днів тому +1

    I love seeing new Angular Signals content. Looking forward to more pattern videos from you and completely zoneless approaches from the Angular dev team after they are done with Signal based forms.
    Thank you for what you do!

    • @deborah_kurata
      @deborah_kurata  19 днів тому +1

      Thank you!
      Have you seen my zoneless video here: ua-cam.com/video/MZ6s5EL7hKk/v-deo.html
      And yes! Anxiously awaiting to see what comes of signal-based forms!

  • @codeSurvivor
    @codeSurvivor 27 днів тому +3

    I really like this pattern, thanks for the video. Kudos to Josh Morony for creating it for Angular, as far as I know.. It would have been nice to mention that somewhere. The way you apply it, is nice but in a way you kind of break the pattern when using the filteredTodos computed signal instead of defining an action explicitly, IMO
    Also I prefer not using tap, and define derived streams and subscribe to them, to be more compliant with the flux pattern in which you change the state at the end of an action

    • @deborah_kurata
      @deborah_kurata  27 днів тому +4

      Thank you!
      Yes, I have seen Josh's videos on this topic. They are great. And I could have mentioned them as another reference. (I think I will add at least one of them to the links area of this video. Thanks for the suggestion. And do you have a suggestion for one in particular that I should reference?)
      But just FYI ... it seems that NgRx used this pattern way before Josh did. The graphic I used in my video was from my Pluralsight NgRx course back in 2018 (updated in 2020). You can find it here: www.pluralsight.com/library/courses/angular-ngrx-getting-started
      Also yes that we could take this pattern further and use explicit actions. That is how NgRx implements it.

    • @Matrium0
      @Matrium0 25 днів тому

      I used to like Josh's content too, but nowadays I feel like he is too much of a functional programming extremist. For the the golden path is somewhere in the middle. If the functional solution has 10 times higher code cost for worse readability (and therefor maintainability) I would rather stick with an imperative approach or a mixture.
      Though his video about error handling with the async pipe are great and a real eye-opener. For me it made me actually use async pipe far less, because he made me realize how ugly good functional-style error handling really get's when usync that pipe. This is something that most content creators here often forget, only showing people the "happy path".
      So I guess what I am saying is that I have mixed feeling about his content.

    • @codeSurvivor
      @codeSurvivor 25 днів тому +1

      @@deborah_kurata Hey! thanks for your answer! I answered a couple of days ago but it was never published, maybe UA-cam doesn't allow comments with links.
      Yep, I suggest Morony's "A New Reactive And Declarative Approach to Angular State Management" blog post. I won't share the link to make sure this comment is published.
      I didn't mean that the flux patter was applied to Angular by Josh Morony, I meant the signals/rxjs bridge pattern that is explained in the blog post I suggested.
      Thanks for your job, Deborah, I'm really a fan, specially of your slower pace and clarity!

    • @deborah_kurata
      @deborah_kurata  25 днів тому +2

      @@codeSurvivor It does appear that YT allows me to publish links but not anyone else. 🤷🏼‍♀
      Thanks for the suggested link. I'll add it to the links for this video.
      And thank you so much for the kind words! ☺

  • @DraaElMizan
    @DraaElMizan 27 днів тому

    Thanks for Sharing Deborah. Another great tut.

  • @xEnergyGamingHD
    @xEnergyGamingHD 27 днів тому +1

    Learned so much, Thank you!

  • @HealmaTech
    @HealmaTech 27 днів тому +1

    I like it raw, and this is one of the best!

  • @AnthonyDev
    @AnthonyDev 27 днів тому +1

    I like to use state pattern, specially with Flutter, but now I can use it with Angular! I'm waiting for the next videos! Thanks, Deborah!

    • @deborah_kurata
      @deborah_kurata  27 днів тому +3

      Thanks for watching!
      I'm curious, why can't you use a state pattern with Angular?

    • @wildflo1492
      @wildflo1492 27 днів тому

      Why not use tanstack query and remove a lot of the boiler plate code of redux pattern

  • @EmilioDegiovanni
    @EmilioDegiovanni 27 днів тому

    Great video Deborah! Thanks

  • @fmontes83
    @fmontes83 27 днів тому +1

    Love this approach! Redux-like for the win!

  • @iuliusciorica282
    @iuliusciorica282 26 днів тому

    Thank you, love your content!

  • @KushanShanuka
    @KushanShanuka 3 дні тому

    great tute, im really interesting about this, and now im waiting for the state update feature,
    by the way thanks a lot for sharing deborah

    • @deborah_kurata
      @deborah_kurata  14 годин тому

      Thank you! And thanks for the reminder!

  • @dsfgato
    @dsfgato 26 днів тому

    Great content! Cheers.

  • @flywheel56
    @flywheel56 27 днів тому +1

    I like your approach of illustrating cognates to the familiar NGRX pattern. I hope you'll soon do the same in relation to the new SignalStore.

  • @juliojimenez450
    @juliojimenez450 24 дні тому

    Another great video that is no longer a surprise! What a wonderful series on angular signals!
    My dream would be a medium-high level course on developing a real project in Angular 18! 😄
    If one day you do it don't doubt that I will be the first to buy it! Keep it up!😉

    • @deborah_kurata
      @deborah_kurata  21 день тому +1

      Thank you for the kind words!
      I've been considering whether to do a course and if so what it would look like. Thanks for your suggestion.

  • @Matrium0
    @Matrium0 25 днів тому +1

    Great explanation, even when I am not a fan of the Redux pattern. Though if you are absolutely set to implement the pattern, this is a very clean way and readable way to do it, with not that much boilerplate. So at least it helps (at least a little bit) with my two biggest concerns with NgRx: readability/maintainability and high-code-cost.

    • @deborah_kurata
      @deborah_kurata  25 днів тому +1

      Thank you!
      Have you looked a signalStore?

  • @erril8285
    @erril8285 25 днів тому

    Great like always :)

  • @tiberseptim7183
    @tiberseptim7183 27 днів тому +7

    Thanks for the video.
    I noticed several problems:
    1. Subscription in Root service is unti-pattern, cause it will live forever.
    2. You need to complete subjects always in onDestroy.
    Anyway, looking at all this boilerplate, one thinks hard before implementing ngrx-like store. Usually you don't need it at all )

    • @dsfgato
      @dsfgato 26 днів тому

      legend

    • @dsfgato
      @dsfgato 26 днів тому

      what's your GitHub account? wanna learn from you

    • @deborah_kurata
      @deborah_kurata  25 днів тому +4

      Hope it was at least interesting if not entirely useful for you. 😊
      1. In this particular case, we want the subscription to last forever (or at least for the life of the application) because it's what makes the application work. If this was instead a small part of a larger application, we could move the service registration to the component itself. Then it would be destroyed when the component was destroyed. (This topic may be worth a separate video?)
      2. You don't need to complete a subject in onDestroy if you use the TakeUntilDestroyed. It will complete the subject when the service is destroyed.

    • @tiberseptim7183
      @tiberseptim7183 24 дні тому +1

      ​@@deborah_kurata yes, I think separate video about subjects completion in case of error, difference between complete() and unsubscribe() may be quite useful.
      I agree, with takeUntilDestroyed you don't need to complete subject. But anyway, in this particular case it's useless, cause service is provided in root.
      UPD. still there are some doubts. When you use takeUntilDestroyed, it ends only subscriptions. But there can still be references to Subject in Subscription object returned by 'subscribe()'. The question is - can the Subject be garbage collected if you do not manually complete it?

    • @CK_SUN
      @CK_SUN 21 день тому

      Why not effect?

  • @richarddefortune1329
    @richarddefortune1329 27 днів тому

    Great video (as usually). I love the patterns you added to mimic "selectors". I didn't like the way it's presented in the NGRX documentation, where the store is accessible on the HTML template.
    If you haven't recorded the next video yet, is there a way to talk a little more about the store itself and concepts, such as initialValue, withMethods, withComputed, rxjMethod(), and so forth.
    I'm glad you recorded this video as I was trying to understand NGRX store by reading the documentation. After watching your video, I will write a small project.
    Thank you so much.

    • @deborah_kurata
      @deborah_kurata  27 днів тому +1

      Thank you for watching!
      I'm considering doing a video on signalStore in the future.

    • @richarddefortune1329
      @richarddefortune1329 27 днів тому +1

      @@deborah_kurata I think I was confused. I thought this was signal store. After watching the video a second time, I realized that you're using signals to mimic the NGRX store.
      I'm so glad you made this video. This means I don't need to wait until the "signal store" is no longer experimental for the project we're working on. We'll use as much as signals we can.
      You're the best angular teacher. Thank you so much 🙏

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      Great! Glad it was helpful.

  • @Brendan2Alexander
    @Brendan2Alexander 19 днів тому

    Excellent Deborah! Do u need to unsubscribe when a subscription exists in a service scoped as a singleton?

    • @deborah_kurata
      @deborah_kurata  19 днів тому +1

      Thanks!
      It's normally good practice to always unsubscribe if you subscribe. That way if someone later changes the scope of the service, it's unsubscribed. Or if someone adds some teardown code (saving current preferences/state on exit for example) that code will be executed.
      But the "because you'll get memory leaks" does not apply in that case. 😊

  • @marianojunior6885
    @marianojunior6885 27 днів тому

    Hi Deborah, first, congratulations on the great video. If I have several subcomponents with many properties to manage state, do I use one service and just one interface to represent the state of the component and subcomponents?

    • @deborah_kurata
      @deborah_kurata  27 днів тому +3

      Thanks!
      I think that it would depend on the complexity of the state and the reusability of the subcomponent(s).
      If a subcomponent (that provides filtering for example) is reusable, it may be useful for it to manage it's own state.
      If a subcomponent is complex (like a paging component with forward, back, jump to page, number of pages, etc), it may be useful for it to manage it's own state.
      If a subcomponent is just "supportive" (like showing additional detail that the main component already manages), it may be useful to have a shared set of state.
      Sorry for the "it depends" answer! 😊

    • @marianojunior6885
      @marianojunior6885 27 днів тому +1

      @@deborah_kurata Thanks!!

  • @user-lu3ew4dk6j
    @user-lu3ew4dk6j 27 днів тому +2

    Don't you think that signalStore will be better for this case, do you?

    • @deborah_kurata
      @deborah_kurata  27 днів тому +1

      Yes! I had intended to mention that in the video and then accidentally omitted it.
      signalStore is a better option. The only advantage that I see this has over signalStore is that it doesn't require a third party state library. (Which may matter to some enterprises.)

  • @rkrao8582
    @rkrao8582 27 днів тому

    Another amazing video. What do you think about Tansact Query ? Do you think it will simplify the approach that you established here to access the server state?

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      Thanks! I haven't looked into TanStack Query, so I don't know how it compares. In a quick glance of the docs, I don't see signals anywhere. But it also says that the Angular version is still "experimental", so maybe signal support is coming?

    • @rkrao8582
      @rkrao8582 27 днів тому

      ​​@@deborah_kurata Yeah, in V5 of TanStack Query Angular, They have all the support with Signals and other stuff latest Angular version. The library is gonna be stable in a few weeks from what I heard.
      Apparently the Architecture team at my workplace believes that it's gonna be a game changer in managing server state in web applications. And they are encouraging us to get a head start on it.
      With Signals being new and hardly caught up on it and there new thing I have to learn !!
      Anyways , You have great teaching skills. Your videos are a great help for me in understanding declarative patterns, rxjs, Signals. Thanks again and keep posting new stuff, Cheers.

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      Thank you! And all the best on your project.
      Maybe a TanStack Query video is in my future at some point... 😊

  • @arthurfedotiew3609
    @arthurfedotiew3609 25 днів тому

    Hi Deborah! Thanks for the great educational content as always 😍 I've got a few questions:
    1. If we have a consumer (e.g. Component) which requires some part of the `currentMember` (in a real world, ther could be more complicated nested objects structure) rather than the whole member, would you recommend to reate more granular slices which would effectively men computed from computed (example of pseudocode: user = computed(() => state().user); userNameUsedByUi = computed(() => user.name())?
    2. Usually, state is not that tiny and maintainable, which would make us create a significant amount of signal based selectors (which would increase even more using the granular selectors (related to above question)). Since each signal is an additional node in the reactive graph, I wonder if there was any performance profiling work done to detect the point where the size of the reactive graph leaves the memory foot print which starts to matter (e.g. on the lower end/mobile) devices?

    • @deborah_kurata
      @deborah_kurata  13 днів тому

      Thank you!
      In the real world, if you have complex data to manage I'd highly recommend signal store or some other state management library. This pattern is best for simpler, smaller-scale projects when a state management library would be overkill.
      Regarding your second question, according to the Angular team; "Signal read does no create a new node in a reactive graph - in this sense we don't need to limit ourselves to the number of signal reads in a template." (From here: github.com/angular/angular/issues/52103#issuecomment-1758168656)

  • @brtk7
    @brtk7 Годину тому

    Do tou recommended using this technique as you described or rxjs signal store?

  • @IgMa-tc1oj
    @IgMa-tc1oj 27 днів тому

    Thank you very much Deborah for your lessons!

  • @alessandrobruni568
    @alessandrobruni568 27 днів тому

    spettacolare!
    Just one question, can the return of the setError be an EMPTY?
    in any case i will try on my own.

    • @deborah_kurata
      @deborah_kurata  25 днів тому

      Thank you! Yes, you can return EMPTY. You'd then want to change the code a bit because if there isn't a set of todos returned (even an empty set of todos), the current code implementation won't turn off the loading flag.

  • @waelmoh
    @waelmoh 25 днів тому

    always helpful, thank you very much for your continuous efforts, but if i can ask for using the state service only in the component level , and its subcomponent and how can the parent and sub interact with this service (wich is not a root service). a small video ? >.< !!

  • @haroldpepete
    @haroldpepete 27 днів тому

    you never let me down, greeat video, what do you think is the most suitable option, make it from scratch or use a library?

    • @deborah_kurata
      @deborah_kurata  27 днів тому +1

      Thank you!
      Yeah, I'd meant to mention that in the video and then neglected to add it. It is much better to use something like signalStore than to do things manually. But I think it helps to understand how this process works.

  • @LMFinney
    @LMFinney 27 днів тому

    Thanks for showing this pattern, but I'm curious if you think this has advantages over using signalStore. signalStore is intentionally not a Redux implementation (even though it's in NgRx), so they aren't directly comparable. But so far, I've been happy with signalStore.
    How do you compare them?

    • @deborah_kurata
      @deborah_kurata  27 днів тому +1

      Thank you!
      signalStore is a much better option. (I had intended on mentioning that in the video and then neglected to!) The *only* advantage that I see this has over signalStore is that it doesn't require a third party state library. (Which may matter to some enterprises.)

    • @LMFinney
      @LMFinney 27 днів тому

      Thanks for responding. I agree with your assessment, but I think it's interesting that Redux _can_ be implemented with signals. It's good to see people trying out different ideas, even if we don't universally adopt them.

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      I appreciate that. Thanks!

  • @GabrielPerez-yg9bi
    @GabrielPerez-yg9bi 27 днів тому

    There's any difference between hard code like you did and using a ngrx signal store?

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      signalStore is a better option. The only advantage that I see this has over signalStore is that it doesn't require a third party state library. (Which may matter to some enterprises or governments.)
      I had intended to mention that in the video and then accidentally omitted it.

  • @raknjarasoa
    @raknjarasoa 22 дні тому

    At 02:55 for initialState, why currentMember is initialized with undefined whereas error is set to null ?
    I personally tend to use only null for data that I have the control. WDYT ?

    • @deborah_kurata
      @deborah_kurata  21 день тому +1

      Regarding currentMember, I like to use undefined because when the application starts the value is literally undefined. It doesn't become defined until the user picks one.
      Regarding error, I was trying to show a number of different data types. There was no reason beyond that. Error could be set to undefined, null, or just empty string depending on your team's preferences.

    • @raknjarasoa
      @raknjarasoa 16 днів тому +1

      @@deborah_kurataThanks. You’re awesome 😎

  • @MrgnUTube
    @MrgnUTube 25 днів тому

    Oh no... it looks like this old damn ngrx ^^

    • @deborah_kurata
      @deborah_kurata  25 днів тому

      That picture came directly from my NgRx materials. But does this approach still look like NgRx after watching the video?

  • @chagamajaykumarreddy1897
    @chagamajaykumarreddy1897 27 днів тому

    great video, very helpful

    • @deborah_kurata
      @deborah_kurata  27 днів тому

      Glad it was helpful! Thanks!

    • @chagamajaykumarreddy1897
      @chagamajaykumarreddy1897 27 днів тому

      I have a doubt that what if we move all that logic inside component because keeping whole that data inside service will never clean untill application browser closed. Component data and Listers will be destroyed once we move to another route right , can you please explain me on this , thanks 🙏

    • @deborah_kurata
      @deborah_kurata  5 днів тому

      It really depends how you have the service registered. If you use providedIn: 'root', then you are correct. That type of service is meant for data to be retained for the entire application (such as user information.) If you register the service in the component itself, then it will be destroyed when the component is destroyed. You don't need to more the logic to a component.

    • @chagamajaykumarreddy1897
      @chagamajaykumarreddy1897 5 днів тому +1

      @@deborah_kurata thanks a lot for sharing. You are super talented

  • @angelocolacicco997
    @angelocolacicco997 24 дні тому +1

    Could we say that... with the power of signlas and rxjs together, we don't need ngex anymore?
    hope it could be so. I hate ngrx

    • @deborah_kurata
      @deborah_kurata  21 день тому

      It depends on the application. Anything complex and these manual techniques become a little unwieldy. That's when NgRx really shines.
      The makers of NgRx also have SignalStore, which is a much more scaled down library that may be worth looking at.