Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is my RxJs Subject not working as expected?

ProductGalleryComponent.html iterates over products. The click event of each image calls the setSelectedProduct function passing to it the product that was clicked.

<div class="row py-3 px-2" style="background: #f5f6f8">
  <div
    class="col d-flex flex-column col-12 col-md-4 col-lg-3 mb-4 gallery-img-col"
    *ngFor="let product of products"
  >
    <img
      class="gallery-img"
      src="assets/img/{{ product.images[0] }}"
      (click)="setSelectedProduct(product)"
    />
  </div>
</div>

The setSelectedProduct function of ProductGalleryComponent.ts calls the setSelectedPRoduct function of the ProductGalleryService, passing the selected product. It then navigates to the SelectedProductComponent.

public setSelectedProduct = (product: ProductModel) => {
    this.productGalleryService.setSelectedProduct(product);
    this.router.navigateByUrl('/selected-product');
  }

ProductGalleryService declares a subject and an observable of the subject. In the setSelecedProduct function, it calls the next function of the subject, passing to it the selected product:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

export class ProductGalleryService {
    public selectedProductSubject = new Subject<ProductModel>();
    selectedProductSubject$ = this.selectedProductSubject.asObservable();

    public setSelectedProduct = (product: ProductModel) => {
        this.selectedProductSubject.next(product);
    }
}

The SelectedProductComponent subscribes to the selectedProductSubject of ProductGalleryService via the constructor. It is expected to receive the product broadcast by ProductGalleryService.selectedProductSubject but the product is never received.

export class SelectedProductComponent {        
    private productGalleryService = inject(ProductGalleryService)

    constructor() {
        this.setSelectedProduct()
    }

  private setSelectedProduct = () => {
    this.productGalleryService.selectedProductSubject$.subscribe((product) => {
      this.selectedProduct = product;
      console.log('selectedProductSubject.selectedProduct', this.selectedProduct)
    })
  }
}

>Solution :

I believe the ProductGalleryService.selectedProductSubject$ subject has already emitted before the SelectedProductComponent subscribes.

How to get around this problem?

RxJS offers another type of Subject – a ReplaySubject.
When subscribing to a ReplaySubject, it will re-emit any previously pushed values.
The ReplaySubject has a buffer size, how many items to store and re-emit. For your use case, I believe you only care about the last one, so BufferSize is 1.

public selectedProductSubject = new ReplaySubject<ProductModel>(1);

  1. Subject vs BehaviourSubject vs ReplaySubject
  2. How to get current value of RxJS Subject or Observable?
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading