Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using single ngOnDestroy in parent component

In our application we have some components that inherit from a BaseComponent.

The base component implements OnDestroy interface and emits with a Subject to notify the children to unsubscribe from eventual open streams.

Is this an acceptable approach or rather every single component should have its own ngOnDestroy implementation? From this article I read that Lifecycle hooks are not inherited.

BaseComponent

export abstract class ComponentBase implements OnDestroy {
  protected destroy$ = new Subject<boolean>();

  ngOnDestroy() {
    this.destroy$.next(true);
  }
}

ChildComponent

export class ChildComponent extends ComponentBase implements OnInit {

 ngOnInit() {
    this.service
      .getById(userId)
      .pipe(takeUntil(this.destroy$)) // this is emitted by the parent
      .subscribe(user => { ...}
 }
}
like image 926
Francesco Avatar asked Dec 13 '22 11:12

Francesco


1 Answers

Is this an acceptable approach or rather every single component should have its own ngOnDestroy implementation?

Acceptable is just a matter of opinion, but I would strongly discourage this approach for the following reason.

@Component({...})
export class MyComponent extends BaseComponent implements OnDestroy {
      public ngOnDestroy() {
         // do work
      }
}

export class BaseComponent implements OnDestroy {
      public ngOnDestroy() {
         // never executed
      }
}

There is no TypeScript warning issued for the above example that the super method is never executed, and so I would be tempted to call this an anti-pattern.

Furthermore, in the future you will be tempted to add additional lifecycle hooks like OnInit to the base class. To which, you'll have to search all of the descendants to ensure they call super.ngOnInit().

While it might seem like more work but it is safer to use encapsulation.

export class BaseComponent implements OnDestroy {
     public ngOnDestroy() {
        // do work
     }
}

@Component({...})
export class MyComponent implements OnDestroy {
  private readonly _base: BaseComponent = new BaseComponent();
  public ngOnDestroy() {
     this._base.ngOnDestroy();
  }
}

There are a lot of articles on the net about the pros/cons between encapsulation vs. inheritance. It's actually a lengthy discussion in computer science, and some programming languages don't support inheritance specifically because of the problems. I guess I'm trying to say that this is a broad topic and a matter of personal choice for you, but it's partly why you asked the question.

https://www.developer.com/design/article.php/3525076/Encapsulation-vs-Inheritance.htm

like image 157
Reactgular Avatar answered Feb 16 '23 01:02

Reactgular