0

When the page is loaded, the data is correctly fetched, and shown, then when leaving the page the data is fetched again and doubled onto the current array. If I have Item: A,B,C then I will have A,B,CA,B,C.

Right now I have the component putting a simple if to check if I need to fetch the data again or not. However, it appears that it is bypassed. I have looked at this and this as well as this.

//home.ts

export class Home implements OnInit, OnDestroy{
  conversations: Array<any>; 

async ngOnInit() {
  this._chatInit();
}

private async _chatInit() {
  this.dataService.loadConversations(); //getter for local storage

  const data = this.messageStorage.hasChats();

  if (data.length) {
    //there is data already loaded
    this.conversations = data;
  } else {
    //there is an empty array, subscribe to it.
    this.messageStorage
    .getChatList$()
    .subscribe(conversation => {
      console.log('Conversation', conversation)
      this.conversations = conversation;
    });
  }
}

//dataService
export class DataService {

  //the object where it is all stored
  private conversations: any = {
    peerToPeer: {},
    groups: {},
  };

  private listOfChats: Array<any> = new Array<any>();
  private bsListOfChats$: BehaviorSubject<any> = new BehaviorSubject<any>(this.listOfChats); 

  public loadConversations() {
    this.storage.get('conversations').then(chat=> {
      this.conversations = chat;
      this.formatChats(this.conversations);//converts the Object to an Array so *ngFor directive can be used
   });
  }

  public hasChats() {
    return this.listOfChats;
  }

  public getChatList$() {
    return this.bsListOfChats$;
  }

}

To clarify, what I want to happen is to load n chats once. When I leave the page and return I want the same n to load, no more, no less.

thanks guys for any help!

Alexander Trakhimenok
  • 6,019
  • 2
  • 27
  • 52
Ctfrancia
  • 1,248
  • 1
  • 15
  • 39

2 Answers2

1

look at TransferState it is used for transfer data between server side (angular universal) and client side, but I think it is ok to use it only for client side

import {makeStateKey, TransferState} from '@angular/platform-browser';

export class DataService {

//the object where it is all stored
private conversations: any = {
    peerToPeer: {},
    groups: {},
};

constructor(
    private state: TransferState,
) {

}

private listOfChats: Array<any> = new Array<any>();
private bsListOfChats$: BehaviorSubject<any> = new BehaviorSubject<any>(this.listOfChats);

public loadConversations() {
    const stateKey = makeStateKey('conversations'); // 1 create stateKey
    const data = this.state.get(stateKey, null as any); // 2 get data from state
    if (data) { // 3 if data in state use it
        this.conversations = data;
    } else {
        this.storage.get('conversations').then(chat=> {
            this.conversations = chat;
            this.formatChats(this.conversations);//converts the Object to an Array so *ngFor directive can be used
            this.state.set(stateKey, {...this.conversations}); // 4 set data to storage
        });
    }
}

public hasChats() {
    return this.listOfChats;
}

public getChatList$() {
    return this.bsListOfChats$;
}

}

fast edit your code, could be rewritten in better way

chestas
  • 124
  • 1
  • 6
  • When fetching data it is from @ionic/storage so there isn't any http request being made – Ctfrancia May 15 '19 at 11:11
  • it doesn't matter. or i don't understand your question( . see example in my answer – chestas May 15 '19 at 11:23
  • Alright, sorry, when you posted it there wasn't code sorry about that. – Ctfrancia May 15 '19 at 11:25
  • Alright, looks like that solved the initial problem, looks like I need to edit my code so that it will update the state and delete the state accordingly, because when I add to the state it is not adding to the array the item. Anyways, thank you for your help with this one! – Ctfrancia May 15 '19 at 11:37
  • don't understand about adding the item to array. maybe you should add different stateKey to different data? ex: `makeStateKey(\`chat_${id}\`)`. and update state for specific key means to reset full data for this key. – chestas May 15 '19 at 11:59
  • with the fast coding you did above it works with loading the chats only once, essentially just reading from state. However, when adding a new item to the conversation object, or when adding a new object to the listOfChats, they are not being shown on screen – Ctfrancia May 15 '19 at 13:30
  • so it looks like I got it to update. The issue was that I was opening a modal, and when opening the modal it would send to the data service the info of the chat, which would be saved to the conversations obj. Now, I modified the code, so that there is a function responsible for updating (or setting) the TransferState, sending the Event to observers, and saving to the SQLite instance on the device – Ctfrancia May 15 '19 at 13:36
0

do this:

@Component({
  //...
  changeDetection: ChangeDetectionStrategy.OnPush
})

check out: https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/

Y_Moshe
  • 424
  • 1
  • 5
  • 11
  • tried that, it doesn't do an initial load and upon re entering it continues to load. – Ctfrancia May 15 '19 at 11:23
  • wait wait wait, why it is async on ngOnInit? is it fine? because I never show use like this. ngOnInit should be a normal function, there u can put any async code, try to fix that and fix _chatInit so it will return something just test it. and btw why u make _chatInit async if u are not using the await keyword over there? u could use a simple promise – Y_Moshe May 15 '19 at 11:37
  • It was there because in the init there was an async call to storage, but since I moved the call I have since taken it off, sorry, typo on my side :^) – Ctfrancia May 15 '19 at 11:39