Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should we unsubscribe from ngxs Selector?

Tags:

angular

ngxs

I'm using ngxs State management. Do I need to unsubscribe from Selectors or is this handled by ngxs?

@Select(list)list$!: Observable<any>;

this.list$.subscribe((data) => console.log(data));
like image 301
Tamer Hussien Avatar asked Jun 11 '19 08:06

Tamer Hussien


People also ask

Do we need to unsubscribe in ngOnDestroy?

Specifically, we must unsubscribe before Angular destroys the component. Failure to do so could create a memory leak. We unsubscribe from our Observable in the ngOnDestroy method.

Should I unsubscribe from NgRx?

Effects are the primary way of handling logic within NgRx. They allow us to observe streams of actions and react to them. We do not need to subscribe to any effect nor do you need to manually unsubscribe. That is handled internally by the NgRx Effects module; once again taking that burden out of our hands.

What is NGXS?

NGXS is a state management pattern and library for Angular. NGXS acts as a single source of truth for your application's state - providing simple rules for predictable state mutations. NGXS is modeled after the CQRS pattern - a pattern implemented in state management libraries such as NgRx and Redux.

Does take RxJS unsubscribe?

One method we can use, is to unsubscribe manually from active subscriptions when we no longer require them. RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .


Video Answer


3 Answers

For the first example you can use in combination with the Async pipe. The Async pipe will unsubscribe for you:

In your ts file:

@Select(list) list: Observable<any>;

In your html file:

<ng-container *ngFor="let item of list | async">
</ng-container>
<!-- this will unsub automatically -->

However, when you want to use the actual subscribe method, you will need to unsubscribe manually. Best way to do that is using takeUntil:

import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';

@Component({
  selector: 'app-some-component',
  templateUrl: './toolbar.component.html',
  styleUrls: ['./toolbar.component.scss']
})
export class SomeComponent implements OnInit, OnDestroy {
  private destroy: Subject<boolean> = new Subject<boolean>();

  constructor(private store: Store) {}

  public ngOnInit(): void {
    this.store.select(SomeState).pipe(takeUntil(this.destroy)).subscribe(value => {
      this.someValue = value;
    });
  }

  public ngOnDestroy(): void {
    this.destroy.next(true);
    this.destroy.unsubscribe();
  }
}

You can use pipe(takeUntil(this.destroy)) for every subscription in your component without the need to manually add unsubscribe() for every one of them.

like image 61
Scuba Kay Avatar answered Oct 16 '22 15:10

Scuba Kay


The Async Pipe solution is usually the best.

Depending on your use case, you can also use the first() operator.

observable.pipe(first()).subscribe(...)

It is shorter than the takeUntil approach and you don't need any unsubscribe.

https://www.learnrxjs.io/operators/filtering/first.html

Beware: This will return a value and unsubscribe. So it can be used if you need a current value from the store and then do something with it. Don't use it to display something on the GUI - it will only show the first change :)

like image 2
Tim Avatar answered Oct 16 '22 16:10

Tim


Yes, if you subscribe manually in the component then you need to unsubscribe.

Best to avoid that if possible and subscribe in the component template using the async pipe.

like image 1
Garth Mason Avatar answered Oct 16 '22 16:10

Garth Mason