1

I know that the ViewContainerRef's remove() destroys an associated view, so is the component that defined it also destroyed? What's the difference between ComponentRef's destroy() vs ViewContainerRef's remove(), and when should I use one over the other?

For example, here I am dynamically creating and displaying a child component.

@ViewChild('taskView', {static: true, read: ViewContainerRef}) vc: ViewContainerRef;

compRef : ComponentRef;

constructor(private CFR: ComponentFactoryResolver){ }

ngOnInit() {
  const factory=this.CFR.resolveComponentFactory(TaskItemComponent);
  const componentRef=this.vc.createComponent(factory);
  this.compRef= componentRef;
}


And I realized that I could remove this dynamically added component in two ways, either by destroying the view using ViewContainerRef's remove, like so:

let vcrIndex: number = this.VCR.indexOf(this.compRef)
this.VCR.remove(vcrIndex);

Or by destroying the component instance itself like so:

this.compRef.destroy();

The effect in my application is the same. However what's the difference between the two? I'm also confused by this earlier stack overflow post: Does ViewContainerRef.clear() remove component from memory?

The top voted answer wrote that

No, if you assign parent component property to componentRef angular won't remove component from memory.

Angular only destroys component and removes its own references to this component. But reference to componentRef remains to live in your component property. So i would assign null to it. This way garbage collect will be able to clear memory"

So does this mean that even after calling destroy() on my componentRef my componentRef is still pointing to the destroyed instance?? What's going on in memory when destroy() or remove() is called?

Shisui
  • 1,051
  • 1
  • 8
  • 23

1 Answers1

3

As MDN documentation states

The main concept that garbage collection algorithms rely on is the concept of reference. ...In order to release the memory of an object, it needs to be made explicitly unreachable.

This means that if you have something that references to your component then it will be still presented in memory.

So does this mean that even after calling destroy() on my componentRef my componentRef is still pointing to the destroyed instance??

It will be still pointing to the destroyed instance until you destroy the class(or service) that keeps componentRef property. In case you destroy component but your class(where you're manipulating dynamic component) is going to live after that then it would be better to assign componentRef property to null.

As for the difference, they are doing the same things:

ComponentRef.destroy()

destroy() {
   if (this._appRef) {
     this._appRef.detachView(this);
   } else if (this._viewContainerRef) {
     // does detachEmbeddedView internally
     this._viewContainerRef.detach(this._viewContainerRef.indexOf(this)); 
   }
   Services.destroyView(this._view);
 }

ViewContainerRef.remove

remove(index?: number): void {
  const viewData = detachEmbeddedView(this._data, index);
  if (viewData) {
    Services.destroyView(viewData);
  }
}
yurzui
  • 205,937
  • 32
  • 433
  • 399
  • I don't think that link tells us much, because the MDN docs you refer to, are about plain javascript whereas Angular might have its own construction to clean this up. – paddotk Jul 11 '22 at 08:14