Function in pages of tab loaded twice


#1

I have a function in my work page that is one of the tab’s page. I have written a function to be loaded once the page enters to request data from API.

Note: Other than the tabs’ pages, the push open pages are working fine.

This was working fine on Ionic 3.0.1, however once I have upgraded to Ionic 3.1.0 when I enters the page the function loaded twice.

Here is my work.ts code

ionViewWillEnter() {
    if(this.auth.authUser()) {
      this.isLogin = true;
      this.userData = this.auth.getUserInfo();
    } else {
      this.isLogin = false;
    }

    if(this.isLogin) {
      this.getClientList(true);
    } else {
      this.clientData = [];
    }
  }

...

private getClientList(resetPage) {
    console.log('loaded getClientList');
  	this.isEmpty = false;
  	this.userData = this.auth.getUserInfo();
  	if(resetPage) {
  		this.content.scrollToTop(0);
  		this.clientPage = 1;
  	}
  	let pageSkip = (this.clientPage-1)*this.clientPerPage;
  	let postData = 'take=' + this.clientPerPage;
  	postData += '&skip=' + pageSkip;
  	postData += '&uid=' + this.userData.userId;
  	if (this.category != '0') {
  		postData += '&category=' + this.category;
  	}
  	if (this.gradeId) {
  		postData += '&grade=' + this.gradeId;
  	}
  	
  	let params = {
			link: 'app/client/my_client_list',
			data: postData,
    }
    this.showLoading('loading...');
    this.api.httpApi(params).subscribe(data => {
    	this.loading.dismiss();
      if (data.status_code == 1) {
        this.clientData = [];
        if(data.data.length > 0) {
        	this.clientData=data.data;
        	// this.productState = 'in';
        	if(this.clientPage < 1) {
        	  this.clientPage++;
        	}

        	if(data.data.length < this.clientPerPage) {
        	  this.isEnd = true;
        	} else {
        	  this.isEnd = false;
        	}
        } else {
        	this.isEmpty = true;
        	this.isEnd = false;
        }

      } else if (data.status_code == 500) {
        this.navCtrl.push('LoginPage');
      } else if (data.status_code == 0) {
      	this.isEmpty = true;
      	this.isEnd = false;
      } else {
        this.showError('network problem');
      }
    },
    error => {
      this.loading.dismiss();
      this.pushLogin();
      // this.showError(error);
    });
  }

console log outputs

Hello AuthService Provider
work.ts:173  loaded getClientList
work.ts:173  loaded getClientList

ionic info

Cordova CLI: 6.5.0
Ionic Framework Version: 3.1.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.3.4
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Windows 10
Node Version: v6.10.2
Xcode version: Not installed

#2

There is a work around which is put your API request function inside the constructor, then the function will only run once. But that’s not solving the problem if you want to use IonViewWillEnter.


#6

The logic in ionViewWillEnterstrikes me as misplaced. It doesn’t want to execute every time this page is going to appear; it wants to execute every time there is a change in authentication status. That is something that should be abstracted into a service:

export interface UserInfo {}
export interface Client {}

export class AuthenticationService {
  authenticated: boolean;
  authNotifier = new ReplaySubject<boolean>(1);
  authToken: string;
  userInfo: UserInfo;
  clientData = [] as ClientData[];

  constructor(private _http: Http) {
  }
  
  login(ui: UserInfo): void {
    this.userInfo = ui;
    this._http.get('/api/clients')
      .map(rsp => rsp.json())
      .subscribe((clients) => {
        this.clientData = clients;
        this.authenticated = true;
        this.authNotifier.next(true);
      }, (err) => {
        this.logout();
      });
  }

  logout(): void {
    this.userInfo = null;
    this.clientData = [];
    this.authenticated = false;
    this.authNotifier.next(false);
  }
}

Now in your page, you have a bunch of choices. Typically, you want something like this in your app component:

rootPage: any;

constructor(auth: AuthenticationService) {
  auth.authNotifier.subscribe((authed) => {
    this.rootPage = authed ? DashboardPage : LoginPage;
  });
}

In this case, your dashboard page knows that you are authenticated and can behave accordingly, simply grabbing userInfo and clientData from the service.