Question:
Ionic 6 AppState change causing duplicate subscription results

Problem

I am making a chat application using Ionic 6 and SignalR for test purposes only. I have a chat detail page, and in this page I am listening a BehaviorSubject which triggers from SignalR. Here is my working principle:


  1. Sender sends a message

  2. Sender triggers "CheckMessage" in SignalR

  3. Receiver's SignalR gets it and triggers a BehaviorSubject which I've subscribed on chat detail page.

  4. It gets the last sent message and show it on the screen.


Everything works as expected, but when I minimise the app and reopen it, after sending/receiving a new message, it shows two times at the screen. When I repeat this, this last message shows at the screen n times (n = how many times that I minimise the app).


How can I solve this issue or what am I missing here?


signalR.cs:


public async Task CheckMessage(int chatId)

{

    try

    {

        await Clients.OthersInGroup("group-" + chatId.ToString()).SendAsync("NewMessage", chatId);

    }

    catch (Exception ex)

    {

        await _log.InsertErrorLog(ex);

    }

}


app.component.ts:


constructor(....) {

    App.addListener("appStateChange", result => {

        if (result.isActive) {

            this.signalR.createHubConnection();

        } else {

            this.signalR.stopHubConnection();

        }

    });

}


ngOnDestroy(): void {

    App.removeAllListeners();

}


signalR.service.ts:


createHubConnection() {

    this.hubConnection = new HubConnectionBuilder()

        .withUrl(this.hubUrl + 'URL?SOME_PARAMETERS', {

            accessTokenFactory: () => USER_TOKEN

        })

        .withAutomaticReconnect()

        .build();


    this.hubConnection.start();


    this.hubConnection.on('NewMessage', id => {

        this.zone.run(() => { 

            this.v.newChatMessage$.next(id);

        });

    });

}


stopHubConnection() {

    if (this.hubConnection) {

        this.hubConnection.stop();

    }

}


async checkNewMessages(id: number) { 

    return this.hubConnection.invoke('CheckMessage', id);

}


v.component.ts:


newChatMessage$: Subject<number> = new BehaviorSubject(0);


detail.component.ts:


sub: Subscription;


ngOnInit() { 

    if (this.sub == undefined) {

        this.sub = this.v.newChatMessage$.subscribe(id => { 

            if (id > 0 && id == this.chat.id) {

                this.service.getLastMessage(id).pipe(take(1)).subscribe(msg => {

                    this.messages.push(msg);

                    this.scrollToBottom();

                });

                

                this.v.newChatMessage$.next(0);

            }

        })

    }

}


sendMessage() {

    this.service.addMessage(MESSAGE_ITEM).pipe(take(1)).subscribe(result => {

        this.messages.push(result);

        this.signalR.checkNewMessages(this.chat.id);

        this.scrollToBottom();

    });

}


ngOnDestroy(): void {

    if (this.sub) { this.sub.unsubscribe(); }

}


Solution

This is happening because in ngOnInit() lifecycly of your detail.component, you get the last message every time it starts:


this.service.getLastMessage(id).pipe(take(1)).subscribe(msg => {

 this.messages.push(msg);

});


Solution: before doing this.messages.push(msg), (or preferably in you service.getLastMessage() function) somehow check that if the last message already exists or not, and if not, then add it; something like:


if (!this.messages.includes(msg)) { //better check whith an id, rather than the text

  this.messages.push(msg);

}


Suggested blogs:

>How can I access specific data inside a JSON file on an Angular?

>HTTP request after another but only care about first one in Angular?

>Why am I getting unexpected parent reaction to child button Angular?

>How can I combine multiple HTTP calls in Angular using RxJS?

>Why Ng serve doesn't work in Angulars?

>How to use JSON:API along with Angular/RxJs?

>Why Ng server doesn't work in Angulars?

>How to operate data before return it using Angular16?

>How to Embed Node Red into existing Angular application?

>Why Angular routing with mat-toolbar is not working?

>Update Observable with value from a different Observable in Angular

>P-Dropdown doesn't set Value manually with Reactive Form in Angular

>Why Apex stacked chart bar is not showing in the x-axis in Angular?

>How can I delete the 3rdpartylicenses.txt file in Angular?


Nisha Patel

Nisha Patel

Submit
0 Answers