DEV Community

Cover image for You may not need ngOnChanges
Hank Chiu
Hank Chiu

Posted on • Updated on

You may not need ngOnChanges

"ngOnChanges" is a lifecycle hook for an Angular component to know when the @Input props are changed. The main drawback of using ngOnChanges is that you have to write much more code to watch a single prop.

Angular team also provides another way to intercept the property changes by setter. If you use the setter technique naively you would find it tediously to write the getter/setter pair and the redundant private variable.

In this article, I would like to share how I improve the setter technique into an npm module - subjectize.

Usage

Say we are building a counter component and would like to do something whenever the count changes. We could have 3 versions of implementation like below(excerpt):

1) By ngOnChanges

class CounterComponent implements OnChanges {
  @Input()
  count: number;

  ngOnChanges(changes: SimpleChanges) {
    if (changes.count) {
      // do something
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2) By naive setter

class CounterComponent {
  @Input()
  get count(): number {
    return this._count;
  }

  set count(value) {
    this._count = value;
    // do something
  }

  private _count: number;
}
Enter fullscreen mode Exit fullscreen mode

3) By Subjectize

class CounterComponent implements OnInit {
  @Input()
  count: number;

  @Subjectize("count")
  count$ = new ReplaySubject(1);

  ngOnInit() {
    this.count$.subscribe(() => {
      // do something
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

They may look fair in such a simple scenario, but things go differently when you have a few Input props to watch. For ngOnChanges, you got lots if logics. For naive setter, you got many boring private variables.

The Subjectize is also a mentally-direct approach: declare a RxJS Subject and subscribe to the Subject for changes, that's it.

The magics

The Subjectize is a TypeScript property decorator. Under the hood, it creates an internal getter/setter for the specified Input prop, just like the naive setter implementation. The Subjectize itself only depends on RxJS, hence you can use it on any ES6 class without Angular. You could also use it for simple state management.

Without saying, there are more things to do to keep the reliabilities. If you are interested, see the source code.

Conclusion

JavaScript getter/setter can be used to watch Input props and subjectize helps you to do that. If you just got fed up with ngOnChanges, give subjectize a try!

Discussion (0)