Would you recommend ChangeDetectionStrategy.OnPush as default changeDetection in Angular 2?
Asked Answered
C

4

10

Would it be a reasonable convention within an Angular-2 project to always use

changeDetection: ChangeDetectionStrategy.OnPush

within a component's decorator? Except when there are clear reasons to use the default-strategy?

Chacma answered 13/9, 2016 at 13:23 Comment(0)
D
9

Especially for big project, the answer is YES and it is always recommended to add it as first thing when you create new components.

The reason is simple: to decrease the change detection process that it is a very expensive operation.

There are many ways of starting the detection when needed, maybe the most used is to trigger manually changeDetection() from the ChangeDetectorRef. Another way is using the async pipe in the view if you are waiting for a subscription value.

To add automatically the OnPush strategy when running the ng generate component command in the terminal, you just need to add the option in your angular.json at the schematics node:

...

    "schematics": {
        "@schematics/angular:component": {
            "changeDetection": "OnPush",
            "prefix": "app",
            "styleext": "scss"
        },
        "@schematics/angular:directive": {
            "prefix": "app"
        }
    }
...
Decretive answered 3/12, 2019 at 13:6 Comment(3)
Below answer by @Marc jackoc should be correct answer. https://mcmap.net/q/1065811/-would-you-recommend-changedetectionstrategy-onpush-as-default-changedetection-in-angular-2Bluebell
@Bluebell if you are working with small projects or if you do not understand exactly how change detection works, you should use the default one, but, especially if you are working with big projects the recommendation even from the Angular team is to use the OnPushDecretive
I just wanted to highlight the risk that if you set a parent component to use OnPush, all the child component instance under that tree are overriden to use OnPush. Its vaguely mentioned in documentation. Refer angular.io/api/core/…Bluebell
C
10

No, I wouldn't recommend that.

Angular 2 change detection is very fast. If you have a small project, I wouldn't bother using it.

If you have a large project, I would likely only use OnPush on certain "leaf" components -- leaf components that have view bindings that only depend on input properties. (A "leaf" component has no child components.)

Beware that OnPush can prevent child components from being automatically change detected, because if nothing caused the OnPush component to be change detected, none of its children will be checked either. Hence the reason I normally only use it on leaf components, to avoid this possible issue.

Also beware that if you use JavaScript reference types for input properties, OnPush will not detect changes you make to the properties of those reference types (e.g., if you add or remove an element from an array, or if you modify an object property's value.)

Cranberry answered 13/9, 2016 at 14:56 Comment(4)
Why is it a problem when it's not a leaf component? Isn't that the whole purpose of OnPush to prune the tree where change detection needs to be run?Bethune
Hi @GünterZöchbauer, if your intent is to prune part of the tree, then you are correct, it is not a problem, but rather a feature. (I've seen cases where people don't understand this, so it gets them into trouble.)Cranberry
I also think that you need to understand change detection quite well in order to be able to use OnPush properly but I think this is the only reason why it is not the default. Besides that AFAIK, the Angular2 team recommends using OnPush because it makes the app much faster. I wouldn't suggest to start with OnPush though, when you start your first Angular2 project, only after you acquired some good understanding on how Angular2 works.Bethune
"because it makes the app much faster" - Does it need to be fast though? Or is it totally fine? Open the chrome profiler, then come back to that decision. Excessive OnPush is a symptom of premature optimisation.Amarillas
D
9

Especially for big project, the answer is YES and it is always recommended to add it as first thing when you create new components.

The reason is simple: to decrease the change detection process that it is a very expensive operation.

There are many ways of starting the detection when needed, maybe the most used is to trigger manually changeDetection() from the ChangeDetectorRef. Another way is using the async pipe in the view if you are waiting for a subscription value.

To add automatically the OnPush strategy when running the ng generate component command in the terminal, you just need to add the option in your angular.json at the schematics node:

...

    "schematics": {
        "@schematics/angular:component": {
            "changeDetection": "OnPush",
            "prefix": "app",
            "styleext": "scss"
        },
        "@schematics/angular:directive": {
            "prefix": "app"
        }
    }
...
Decretive answered 3/12, 2019 at 13:6 Comment(3)
Below answer by @Marc jackoc should be correct answer. https://mcmap.net/q/1065811/-would-you-recommend-changedetectionstrategy-onpush-as-default-changedetection-in-angular-2Bluebell
@Bluebell if you are working with small projects or if you do not understand exactly how change detection works, you should use the default one, but, especially if you are working with big projects the recommendation even from the Angular team is to use the OnPushDecretive
I just wanted to highlight the risk that if you set a parent component to use OnPush, all the child component instance under that tree are overriden to use OnPush. Its vaguely mentioned in documentation. Refer angular.io/api/core/…Bluebell
I
0

No.

Why? not because the default change detection strategy is better. But because switching from it to OnPush can be cumbersome and impactful. You might also face few issues if you are using any 3rd party applications that do not use OnPush.

I just don't get it why a lot of people are joining the default change detection strategy bandwagon and are recommending it. In my opinion angular should have always had only one option - OnPush. This is not something new. Silverlight/WPF do this via INotifyPropertyChanged

public string UserName 
{
    get { return this.username; }
    set
    {
        this.username = value;
        // tell the UI that this UI bound property has been changed and that it is time to update the UI
        PropertyChanged(this, new PropertyChangedEventArgs("UserName")); 
    }
}
Illustrative answered 5/9, 2019 at 10:21 Comment(1)
Why the downvote!? I came from WPF/SL world. I didn't see any problem with the code telling UI when to refresh the UI component (via ProperyChanged). The accepted answer already mentioned how this can impact a big project. You never know how complex/big your application can get, why would you risk a switch later?. Sure, this might sound like a premature optimization, but I don't see an optimization like this can add any complexity (other than adding some boilerplate code) and appears to be worth it.Illustrative
A
-2

You could use immutable.js which would 'freeze' all your objects and not allow modification, this would be a far safer route if you want to use OnPush globally, to prevent errors in component binding

Avon answered 14/12, 2017 at 13:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.