💥 Angular Mistake #5: 🛑 STOP Overusing OnPush Change Detection

แชร์
ฝัง
  • เผยแพร่เมื่อ 25 ธ.ค. 2024

ความคิดเห็น • 59

  • @AngularUniversity
    @AngularUniversity  10 หลายเดือนก่อน +2

    If you are looking to learn Angular, check out the courses from Beginner to Advanced at the Angular University - angular-university.io/

  • @dbbbbbbb1952
    @dbbbbbbb1952 3 หลายเดือนก่อน +1

    On push has made my change detection substantially more predictable and less buggy. I’ve rewritten all projects to use on push.

  • @bartekaszczuk5201
    @bartekaszczuk5201 10 หลายเดือนก่อน +18

    Personally I think OnPush should be used everywhere. I would use it as a default if it was possible.

    • @AngularUniversity
      @AngularUniversity  10 หลายเดือนก่อน +1

      This is the myth I hope the video helps tackle. There is no good reason to use it as default, the complexity cost that comes with it is not a good fit for a lot of teams.

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

      @@AngularUniversity To be honest, I haven't watched the video yet. I'll check it later, perhaps my view will change.

    • @AngularUniversity
      @AngularUniversity  10 หลายเดือนก่อน +1

      @@bartekaszczuk5201 Awesome, I'm curious to hear your thoughts once you have watched it 😊

    • @vazzzher
      @vazzzher 10 หลายเดือนก่อน +2

      you can adjust angular cli so that newly created components will have onPush by default by running this or appending schematic in angular.json by hand
      ng config schematics.@schematics/angular.component.changeDetection OnPush

    • @FredRanger-1
      @FredRanger-1 8 หลายเดือนก่อน

      I agree. I watched the video and I feel like I have two problems with it:
      1. The complexity really only comes into play when deciding on a "pattern" for your team to follow, which will be handled by the leads/seniors. Once it's in play, be it through immutability, centralized stores, RXJS pipes, or signals, it really won't be hard for anyone, even a junior, to just copy how everything else is done.
      2. The performance difference is being downplayed hard. Yes, in many cases you will not need OnPush, because your components will be very dumb. But, not using OnPush allows for poor practices to be used (e.g. binding to a mildly complex function) without consequence. I also think that if you are more relaxed towards it, when a performance problem does come around, you may not be prepared architecturally to effectively debug/refactor it.
      IMO there are certainly times where using default CD will benefit the code. But, you should still take the mindset of enforcing everything be OnPush by default, and only flip it back if there is solid justification for it. That's especially the case these days, where it's so easy to make a reactive template.

  • @adambickford8720
    @adambickford8720 10 หลายเดือนก่อน +5

    There's yet another way to do `OnPush` using reified reactivity, i.e. using `Observables` and `BehaviorSubject`s instead of mutating references with new objects. This is more complex still but makes managing concurrency easy if you need to (debounce, retry, etc). It doesn't really require zone.js and is much closer to a signal based solution.

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

      That is also possible, you can do it without NgRx too. 👍

  • @JonoSchoeman
    @JonoSchoeman 10 หลายเดือนก่อน +2

    Just my opinion based on a couple of enterprise-grade projects I've worked I think this (i.e. using Default change detection) encourages bad application architecture & component hygene. With the default setting, engineers will tend to use components instead of services for state management / manipulation, which could result in hundreds of lines of spaghetti code that handles data fetching, data management & UI interaction (no clean separation of concerns). Mutating state (as in your example) like that in components can be a nightmare to debug / test. (That being said, OnPush with markForCheck() or detectChanges() being called everywhere is even worse, but if that is something engineers try to avoid, I've found "purer" / simpler components are created).
    There is also the mental model overhead of knowing when to use OnPush vs Default, rather than always following a single pattern.
    The cleanest approach I've found is having services that handles data updates & provides immutable state via observables, which allows all the components to have less business logic.

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

      You can do bad architecture and bad code with either OnPush and default change detection. You can write clean components and services with default just as well, with the added benefit that it's much more straighforward and easy to use. , it's just a myth that OnPush will help avoid this.

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

    thank you for making this content. ive been working with angular for a few years now, yet i still get a lot of value from your content

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

      Thank you, it's awesome to hear that 😊

  • @danhobbs75
    @danhobbs75 10 หลายเดือนก่อน +4

    I'm interested to see what you're going to say, Vasco. I ALWAYS use OnPush to keep change detection localised to the component tree segment in question rather than need the full check of the default behaviour.

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

      This does make sense. I think the big difference is that right from the start I built with a centralised immutable store which delivers everything into components using Observables. I've also found using signal inputs since v17.2 a game changer for simplicity of component design. Thanks for this excellent explanation as always, Vasco!

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

    Very solid arguments, thank you very much!

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

      You're welcome Julien, I'm glad the video helped. 😊

  • @AleksandarT10
    @AleksandarT10 10 หลายเดือนก่อน +1

    Great points! Keep up them coming!

  • @omarabdelhameed1066
    @omarabdelhameed1066 10 หลายเดือนก่อน +1

    Great Video ! :)

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

      Thank you, glad you enjoyed it 😊

  • @NuncNuncNuncNunc
    @NuncNuncNuncNunc 9 หลายเดือนก่อน +1

    I think the claim that using OnPush requires a vastly different way of coding components vastly overstates the changes needed. I've changed default generator to add OnPush with almost no changes ever needed. The big difference I see between my code and @AngularUniversity is that AU is using plain old container objects instead of Observables. In my experience almost all data such as Course[] is supplied from an asynchronous provider, e.g. advancedCourses$: Observable.
    In the example code, I think a separate component would solve the problem. Alternatively, I think injecting the ChangeDetectorRef and marking for update would work. Have not tested either

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

      Thank you for commenting, but that is actually maybe the main difference. OnPush makes it hard to use just plain member variables, which is a very natural programming model. OnPush forces you to either feed the data via Observables, create separate components just to have an input for things that would otherwise not be a separate component, or use ChangeDetectorRef everywhere. This is all doable, but significantly more complex than what default change detection gives you, just plain member variables without the need for Observables. 👍

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

      @@AngularUniversity But the problem is that dynamic plain old containers just don't appear on any reasonably sized app, i.e. any app that makes API calls. If it's not making any API calls it's very likely static and change detection does not matter. The actual angular-course page makes a request to get the courses. Does it not use async? The lessonsService? If you managed that without observables, that's a lesson I'd love to learn!

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

      @@NuncNuncNuncNunc Yes correct you don't need Obervables or the async pipe. With default change detection, you can just have a plain member variable and access it from the template.

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

      @@AngularUniversity I think you've completely missed my point. I'll be direct - plain old javascript containers are not used for dynamic content. Since they are not used, there is no added complexity of using observables. They are already baked in. The consequence is that there is no mental overhead nor additional code overhead to always using OnPush.
      Do your services on the Angular University return plain objects? If so, please, please, please make a lesson on how to that and include features like isLoading, onSuccess, onFailure, etc.

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

      @@NuncNuncNuncNunc and just to be clear, what do you mean by Javascript containers, you mean primitive Objects and Arrays, or something else? usually my services return Promises, you can get the primitive value with async / await then assign it to a member variable.Your component data does not have to be Observables in Angular, it can be just plain data, objects and arrays as member variables. It works beautifully, very simple and intuitive. 👍 But that programming model is essentially not doable in OnPush in a practical way.

  • @michaelrtan09
    @michaelrtan09 10 หลายเดือนก่อน +1

    Hello, first of all, thank you for making all these amazing angular guide/best practice videos. I'm planning to refactor most part of our project code to be signal based. I'm wondering if It would be more advantageous to use onPush change detection on signal based pages/components? Thanks and more power!

    • @AngularUniversity
      @AngularUniversity  10 หลายเดือนก่อน +1

      If you refactor the code into signals, it will work with both OnPush and default change detection, although signals are not plugged yet into default change detection. OnPush is already integrated with signals, if you consume a signal in an OnPush template it will mark the component as dirty, just like with the async pipe. I'm personally still waiting to see what signal-based change detection will look like, before starting to refactor into signals. 👍

    • @michaelrtan09
      @michaelrtan09 10 หลายเดือนก่อน +1

      @@AngularUniversity I see, thanks for this info, I am using onpush change detection on my pages/components so I think this is ok.

  • @wizard6928
    @wizard6928 10 หลายเดือนก่อน +3

    I heard an opinion that onPush should be used most of the time to force good architecture on developer, that is to use async pipes and split components to dumb and smart so the data is passed through inputs etc and I think it is quite good point
    Modifying objects and arrays in this case can be tricky indeed but I find myself not doing that most of the time as after some update on page data needs to be refreshed with DB anyways so then streams come into play and async pipes
    So I think modifying objects and arrays inside inputs could be called edge cases
    Interesting video anyways, I'm curious how would you respond to that 😊

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

      it's a myth that the constraints that OnPush brings with it are somehow beneficial. Those constraints are inconvenient for the developer and come at a price. Most of the times, that complexity price is not worth paying. 👍 I think we should use the right tool for the job and not making things unnecessarily complex without any added benefit.

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

    Thank you for a great video, as usual. I have a data table with over 100 columns and over 300 rows. The table data is partially updated multiple times per second, through a websocket connection and the speed of the app is of paramount importance. Is onPush making a difference here or not? Tried with both strategies and I do not notice a performance difference. So it is more on how performant is a material data table, rather than the Angular's change detection merit on final user experience !?

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

      I think that this is a great example, that even with a fair amount of data, default change detection is not an issue; Usually what is harming performance in situations with large tables with a large number of DOM elements is the number of DOM elements itself, and not the change detection. I recommend trying Angular CDK virtual scrolling, it works just like ngFor - th-cam.com/video/CemKQarA2xM/w-d-xo.html 😊

  • @anutaNYC
    @anutaNYC 10 หลายเดือนก่อน +1

    Other developer on here said use on push all the time

    • @AngularUniversity
      @AngularUniversity  10 หลายเดือนก่อน +1

      I hope I've explained well in the video why I think we shouldn't do it: the complexity cost is not worth it in most situations. 👍

    • @anutaNYC
      @anutaNYC 10 หลายเดือนก่อน +1

      @@AngularUniversity I didn't even know it existed to be honest!! My issue now with angular is how more complex it's getting more like Java than the true front end! Patterns and now new things!!

    • @AngularUniversity
      @AngularUniversity  10 หลายเดือนก่อน +1

      @@anutaNYC No need to feel like you have to use it if you don't need it, the default change detection mechanism works great for most applications. 👍

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

      @@AngularUniversity I have a change detection error because angular sees the component as null but then when I reveal the actual component on the dom it finds it and complains, the issue is I'm passing the reference to that component by input binding and I can't find the solution