Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ionic page constructors are executing multiple times #5960

Closed
nikiben opened this issue Mar 28, 2016 · 31 comments
Closed

Ionic page constructors are executing multiple times #5960

nikiben opened this issue Mar 28, 2016 · 31 comments

Comments

@nikiben
Copy link

nikiben commented Mar 28, 2016

Short description of the problem:

The constructor execute when user navigates from page1 to page2 and then back to page1 (the second time), so the constructor executes every time user navigates to different page that has already been loaded. The configurations, models and variables are been reset or re-initialized.

What behavior are you expecting?

I was expecting the constructor to init just once when the page loads, not every time user navigates to already loaded page.

Steps to reproduce:

  1. create new ionic v2 project
  2. create 2 pages. Page1 and Page2
  3. Log a sample message in the constructor like below in Page1.js and Page2.js
  4. Navigate to Page2 and then back to Page1. Inspect the console and you'll notice that the message "My Constructor has been initialized....." is printed to the console everytime
    constructor(nav) {
        this.nav = nav;
        **console.log("My Constructor has been initialized.....");**
    }

Other information: (e.g. stacktraces, related issues, suggestions how to fix, stackoverflow links, forum links, etc)

Which Ionic Version? 1.x or 2.x
$projectfolder>ionic -v
Ionic 2.0.0-beta.19

Run ionic info from terminal/cmd prompt: (paste output below)

Your system information:

Cordova CLI: 5.4.1
Gulp version: CLI version 3.9.0
Gulp local: Local version 3.9.1
Ionic Version: 2.0.0-beta.3
Ionic CLI Version: 2.0.0-beta.19
Ionic App Lib Version: 2.0.0-beta.9
OS:
Node Version: v5.4.1

@Ionitron Ionitron added the v2 label Mar 28, 2016
@jgw96
Copy link
Contributor

jgw96 commented Mar 29, 2016

Hello! Thanks for opening an issue with us! I am having trouble reproducing this issue with the exact steps you listed above. Would you be able to maybe give me a full sample of the code your having this issue with? Thanks again!

@jgw96 jgw96 added the needs: reply the issue needs a response from the user label Mar 29, 2016
@nikiben
Copy link
Author

nikiben commented Mar 30, 2016

See below sample code... You can also download the full code from my webspace cutePuppyPics.rar

App.js

import 'es6-shim';
import {App, IonicApp, Platform, MenuController} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Page4Page} from './pages/page-4/page-4';
import {Page5Page} from './pages/page-5/page-5';


@App({
  templateUrl: './build/app.html',
  config: {} // http://ionicframework.com/docs/v2/api/config/Config/
})
export class MyApp {
  static get parameters() {
    return [[IonicApp], [Platform], [MenuController]];
  }

  constructor(app, platform, menu) {
    this.rootPage = TabsPage;
    this.app = app;

    this.page4 = Page4Page;
    this.page5 = Page5Page;

    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }

  openPage(page) {
      this.app.getComponent('menu').close();
      let nav = this.app.getComponent('nav');
      nav.setRoot(page);
  }
}

`

First Page

import {Page, NavController} from 'ionic-angular';

/*
  Generated class for the Page4Page page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Page({
  templateUrl: 'build/pages/page-4/page-4.html',
})
export class Page4Page {
  static get parameters() {
    return [[NavController]];
  }

  constructor(nav) {
    this.nav = nav;
    console.log("Initiating Page4....");
  }
}

`

Second Page

import {Page, NavController} from 'ionic-angular';

/*
  Generated class for the Page5Page page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Page({
  templateUrl: 'build/pages/page-5/page-5.html',
})
export class Page5Page {
  static get parameters() {
    return [[NavController]];
  }

  constructor(nav) {
    this.nav = nav;
    console.log("Initiating Page 5....");
  }
}

`

image

@Ionitron Ionitron removed the needs: reply the issue needs a response from the user label Mar 30, 2016
@nikiben
Copy link
Author

nikiben commented Mar 30, 2016

Sorry, forgot to mention, the navigation is from the menu. I.e navigate to page2 from menu and back to page1 from the menu.

Thanks

@nikiben
Copy link
Author

nikiben commented Apr 1, 2016

Tested on Device... Same issue

@nikiben
Copy link
Author

nikiben commented Apr 28, 2016

Hello, can you please advise on this? Thanks

@jgw96
Copy link
Contributor

jgw96 commented Apr 28, 2016

Hello! Sorry it has taken so long to get back to you. So i made a plunker (http://plnkr.co/edit/mJQG4dy3uqaZlQUQfvFZ) for you to check out that i think might help with some of the theory behind this issue. So you will see from my plunker that an alert is set in the constructor of the home page (the first page you see) and the page that is navigated too when you hit the thanks! button (page 1). So if you test this plunker you will see that the constructor for the home page is only initialized once, you only see the home page alert when the app is first loaded. Now you will notice that it does alert every time page 1 is navigated too, this is expected behavior. When you click that back button on page 1 that navigates you back to the home page, it destroys that instance of the page 1 page, therefore when it is navigated to again it has to be constructed again. So to sum all this up, your root page (the page your app starts on usually) will never have to be constructed except when the app first loads, but any page that you push and then close will have to be constructed ever time it is navigated to.

So with a sidemenu app such as yours, where your using setRoot every time you navigate to a page from the menu is gonna "reset" that page every time it is navigated too because its setting it as root, therefore causing it to be constructed every time it is navigated too. This is expected behavior and should not cause any issues with your app.

I hope i explained all this well! Thanks for using Ionic! I am going to close this issue for now as i believe the above should clear it up, but feel free to comment still!

@jgw96 jgw96 closed this as completed Apr 28, 2016
@nikiben
Copy link
Author

nikiben commented Apr 28, 2016

Hi Justin,

So I modified the plnkr and I tried putting the code below in Page1. Seems
like the main starting page (root Page) still gets re-constructed.

import { IonicApp, Page, NavController } from 'ionic-angular/index';
import { HomePage } from './home.ts';

@page({

  • templateUrl:"page1.html"*
    })
    export class Page1 {
  • constructor(public app: IonicApp, public nav: NavController) {*
  • alert("page 1 is constructed")*
  • }*
  • backToMain() {*
  • console.log('Hello.....');*
  • // this.nav.setRoot = HomePage;*
  • // this.nav.popToRoot();*
  • let nav = this.app.getComponent('nav');*
  • nav.setRoot(HomePage);*
  • }*

}

Ebenezer Isaac
Director | Entrepreneur
Ben-Eris Technology Inc.
C: (647) 704-3823
www.beneristechnology.com

Confidentiality Notice: This e-mail, including any attachments, is for the
sole use of the intended recipient(s) and may contain private,
confidential, and privileged information. Any unauthorized review, use,
disclosure or distribution is prohibited. If you are not the intended
recipient or this information has been inappropriately forwarded to you,
please contact the sender by reply e-mail and destroy all copies of the
original.

On Thu, Apr 28, 2016 at 11:41 AM, Justin Willis notifications@github.com
wrote:

Hello! Sorry it has taken so long to get back to you. So i made a plunker (
http://plnkr.co/edit/mJQG4dy3uqaZlQUQfvFZ) for you to check out that i
think might help with some of the theory behind this issue. So you will see
from my plunker that an alert is set in the constructor of the home page
(the first page you see) and the page that is navigated too when you hit
the thanks! button (page 1). So if you test this plunker you will see that
the constructor for the home page is only initialized once, you only see
the home page alert when the app is first loaded. Now you will notice that
it does alert every time page 1 is navigated too, this is expected
behavior. When you click that back button on page 1 that navigates you back
to the home page, it destroys that instance of the page 1 page, therefore
when it is navigated to again it has to be constructed again. So to sum all
this up, your root page (the page your app star ts on us ually) will never
have to be constructed except when the app first loads, but any page that
you push and then close will have to be constructed ever time it is
navigated to.

So with a sidemenu app such as yours, where your using setRoot every time
you navigate to a page from the menu is gonna "reset" that page every time
it is navigated too because its setting it as root, therefore causing it to
be constructed every time it is navigated too. This is expected behavior
and should not cause any issues with your app.

I hope i explained all this well! Thanks for using Ionic! I am going to
close this issue for now as i believe the above should clear it up, but
feel free to comment still!


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#5960 (comment)

@jgw96
Copy link
Contributor

jgw96 commented Apr 28, 2016

Hey! So yeah, since your doing a setRoot on the home page it is going to be reconstructed when you navigate to it because its being reset as the root and has to be reinitialized.

@nikiben
Copy link
Author

nikiben commented Apr 28, 2016

Thanks Justin,

Is there a documentation that shows how to navigate through the app without
reconstruction every time?

How would one achieve this?

Ben
On Apr 28, 2016 4:12 PM, "Justin Willis" notifications@github.com wrote:

Hey! So yeah, since your doing a setRoot on the home page it is going to
be reconstructed when you navigate to it because its being reset as the
root and has to be reinitialized.


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#5960 (comment)

@jgw96
Copy link
Contributor

jgw96 commented Apr 28, 2016

@nikiben so if your on your root page and you navigate to a different view, then to get back to your root page all you have to do is use nav.pop(rootPage). There is no need to set it as root again before you navigate back to it. This will keep it from reconstructing (: .

@nikiben
Copy link
Author

nikiben commented Apr 28, 2016

@jgw96 I notice this happens as well with the Ionic menu starter tutorial project https://github.com/driftyco/ionic2-starter-tutorial. The page get's reconstructed every time user clicked on menu items. But this is different in Ionic 1.

My concern is that if I have an http call or if i'm loading some sort of data on a pop and push page that means i will be loading the resource(s) everytime I visit that page (since the instance will be destroyed). I just want to load the data once until it's refreshed by user.

Is there a way to workaround this?

@paulsson
Copy link

@jgw96 is there a reason that NavController setRoot can't cache other root pages that have been used and replaced by other pages? I agree with @nikiben that it is not ideal to have to recreate a page (along with model data, data retrieval, etc) every time it is set as root on the NavController.
Can an option be added to cache a root page even when it is removed so the next time it is set as the root page it can just start at its last state?

@deepakkumarsharma-tudip
Copy link

hmm

@wodka
Copy link

wodka commented Dec 7, 2016

I'm having a similar issue but I call setRoot() only once!

the component looks like this:

export class Chats {
    constructor() {
        console.log('start chat component!', new Error);
    }
}

these are the logs even though there is only one this.nav.setRoot(Chats); call. The Constructor is called twice, once at NavControllerBase._setPages and once at NavControllerBase._trnsFinish

start chat component! Error
    at new Chats (MyApp/src/pages/chats/chats.ts:32:46)
    at new Wrapper_Chats (/AppModule/Chats/wrapper.ngfactory.js:7:18)
    at _View_Chats_Host0.createInternal (/AppModule/Chats/host.ngfactory.js:16:21)
    at _View_Chats_Host0.AppView.create (MyApp/node_modules/@angular/core/src/linker/view.js:98:21)
    at _View_Chats_Host0.DebugAppView.create (MyApp/node_modules/@angular/core/src/linker/view.js:308:44)
    at ComponentFactory.create (MyApp/node_modules/@angular/core/src/linker/component_factory.js:157:36)
    at NavControllerBase._viewInit (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:333:44)
    at NavControllerBase._nextTrns (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:205:18)
    at NavControllerBase._queueTrns (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:189:14)
    at NavControllerBase._setPages (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:131:21)
start chat component! Error
    at new Chats (MyApp/src/pages/chats/chats.ts:32:46)
    at new Wrapper_Chats (/AppModule/Chats/wrapper.ngfactory.js:7:18)
    at _View_Chats_Host0.createInternal (/AppModule/Chats/host.ngfactory.js:16:21)
    at _View_Chats_Host0.AppView.create (MyApp/node_modules/@angular/core/src/linker/view.js:98:21)
    at _View_Chats_Host0.DebugAppView.create (MyApp/node_modules/@angular/core/src/linker/view.js:308:44)
    at ComponentFactory.create (MyApp/node_modules/@angular/core/src/linker/component_factory.js:157:36)
    at NavControllerBase._viewInit (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:333:44)
    at NavControllerBase._nextTrns (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:205:18)
    at ti.resolve (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:156:19)
    at NavControllerBase._trnsFinish (MyApp/node_modules/ionic-angular/navigation/nav-controller-base.js:500:9)

@KarimMesallam
Copy link

KarimMesallam commented Dec 29, 2016

@jgw96 I have a similar issue when I logout then login again to my app.

I use setRoot when logging in, and setRoot when logging out. I've tried push when logging in (which is not a good practice since it keeps the login page in the stack) but it still didn't fix the issue.

Whenever I logout and login again, the constructor of tab1Root increments in execution.

In the first time, I only login, and the constructor run once normally, then after a logout and a login, it runs twice, then another logout and login and it runs thrice, and so on...

The only workaround I can think of is using window.location.reload() after logging out, but I can't do this in the app since it will break the native feel and seem buggy.

@pittdewaard
Copy link

pittdewaard commented Jan 5, 2017

Hi,
I'm also use setRoot(page) to navigate between my pages, in some of my pages I subscribe to an observer, after while of navigation for and back I have several subscriptions to the same observer, even I can unsubscribe, I need two subscriptions over the complete app livecycle, without having multiple subscriptions, especially because after a while nodejs/events.js runs in memoryleaks!

some ideas?

KR

Pitt

@jeanbaptistevilain
Copy link

Hi @jgw96,
Same problem as @KarimMesallam here. We're using setRoot to init the navigation stack after a login or a logout, and the post-login controller is initialized 3 times in a row after a login - logout - login cycle.
Therefore ionViewDidEnter is also executed 3 times, which produces unexpected behavior in our app. Using ionViewDidLoad instead did not make any difference, FWIW.
Can you please advise ? I could not find a workaround for this one, and it has a major impact on the navigation in our app.

Thanks in advance

@emgould
Copy link

emgould commented Jan 11, 2017

Same problem. Using setRoot based on auth state. constructors running multiple times if I use tabs.

@megharajdeepak
Copy link

Though it is intended behaviour right now, I reckon ideally there should be an option for the developer whether to retain the page\view as-is in memory or whether he\she wants to reload it every time he\she land up on the page.

A property on ionic page like 'destructionPolicy' which can take values as 'auto' or 'never' would help. That's just me though ;)

Thanks for ionic2...
Cheers!

@wodka
Copy link

wodka commented Jan 13, 2017

@megharajdeepak I do not thing it is intended that when you call setRoot once it will trigger the construct multiple times.

@chanphillip
Copy link

Just passing by, try wrapping zone.run to setRoot
I had the same issue and this workaround is still working properly.

See more about this:
https://forum.ionicframework.com/t/after-setroot-tabspage-the-default-tab-page-appears-twice/71770/10

@samarthagarwal
Copy link

Going back and forth between pages seems to create multiple copies of the pages, each one active behind the scenes, even if the parameters are different. I am using socket.io, and receiving the same message multiple times on the messages page. If I go back and come back to the messages page, the new message will show up one more time than the last time.

@jeanbaptistevilain
Copy link

@chanphillip many thanks for passing by ! Your suggestion worked perfectly, root pages aren't duplicated anymore. I wish we had a proper explanation as to why this happens, I'm still a bit puzzled myself but it's good to know that we've got a workaround. Cheers !

@ProlificBlueprint
Copy link

I seemed to run into this problem when implementing links in the url

// caused my controllers to be loaded twice
IonicModule.forRoot( Spotlight , { mode: 'ios' }, { links: app_links }),

// only loaded once as expected
IonicModule.forRoot( Spotlight , { mode: 'ios' }),

something happening with Ionic taking over routing .

@AhmetFUsta
Copy link

I am still facing this issue, also in a login - logout cycle where the contructor (and ngOnInit) are executed multiple times (actually the entire page is rendered multiple times) and the amount of times keeps increasing everytime the cycle happens, it resets when the app or page is reloaded. So basically the same thing as people mentioned before me.
I tried the NgZone approach and it did not fix/bypass this issue.
Do you know anything about this @jgw96 ?

@unnikrishnan-ateam
Copy link

I am also facing the same issue. Is there any workarounds? I tried the method mentioned by @chanphillip but unfortunately it's not working for me. If there are any other workarounds or methods to fix this please share here. This issue is killing my app navigation.

@jeffersoncostas
Copy link

I have the same issue, the @chanphillip workaround its not working :/

@bhumin3i
Copy link

i have same issue any one have solution?

@gurnard123
Copy link

I have the same issue. This has been opened for more than 2 years and this is a common piece of funcitonality, login/logout. How should this be performed so that multiple observers are not created. subscription to platform.resume is created each time a page is loaded.

@DBLTecnologia
Copy link

Same here, any solutions?

@ionitron-bot
Copy link

ionitron-bot bot commented Sep 11, 2018

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Sep 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests