ionViewWillEnter vs ionViewDidEnter

sebaferreras answer is great but it is missing some points.

First, about ionic life cycle. If you write down all ionic events and put a console.log in each, you will see the scenario:

constructor --> ionViewDidLoad --> ionViewWillEnter --> ionViewDidEnter --> ionViewWillLeave --> ionViewDidLeave --> ionViewWillUnload.

constructor run first when the page is initiated. This is the best place for you to declare default values for your variables.
ionViewDidLoad is fired when the view is completely loaded. It means you can attach DOM element here.

ionViewWillEnter runs when the page is about to enter and become the active page. ionViewDidEnter runs when the page has fully entered and is now the active page. ionViewDidEnter will fire after all synchronous in ionViewWillEnter completed. To prove it, just put heavy code into ionViewWillEnter:

ionViewWillEnter(){
    console.log("ionViewWillEnter")
    for(let i = 0; i < 100000; i++){
      console.log(i);
    }
}
ionViewDidEnter(){
    console.log("ionViewDidEnter")
}

Run your code and you will see it take so long time to launch your page. So never put heavy synchronous code into ionViewWillEnter. Just use asynchronous in ionViewWillEnter and move all synchronous code to ionViewDidEnter. Because in there, your page is entered and it will make a better UX.


The answer is quite simple and, as always, the best way to see what's going on behind the scenes is to inspect the source code of Ionic.

Long story short: the ionViewWillEnter lifecycle hook is triggered before the page transition begins, and the ionViewDidEnter is triggered after the transition finishes. Please take a look at the end of this answer to see the reference to the source code.

So, when you should use each of these hooks? There must be several possible scenarios, so these are only a few ideas based on some applications I've worked on.

  • Sometimes you want to update some information on the page every time the user opens that page; that may require making an HTTP request to a remote API to fetch some data. In that case, we could say that using the IonViewWillEnter seems like the right option, so you can make the request as soon as possible, obtaining the response sooner as well.

  • The same applies when you need to interact with the DOM for some reason because the DOM has been already loaded when the IonViewWillEnter is executed, so this could help you to initialize the page as soon as possible, and with a little bit of luck the page could be shown to the user ready to be used.

  • The same is valid when you need to initialize the view with some parameters that you get from the previous view. In this case, since it's a very simple operation, you can use the ionViewWillEnter lifecycle hook and the view will be shown already initialized to the user.

So when should you use the ionViewDidEnter then?

  • I've noticed that sometimes when executing the app on very old android devices (with less than 512mb - 1gb RAM), the animation can be a little bit lagged when making a request to the API in the ionViewWillEnter, so it'd be a good idea to make these requests to the API in the ionViewDidEnter to make sure that the animation is finished

  • In some apps I've been asked to include some fancy animations to the elements of the pushed page, like bringing part of the content from the bottom, fading some other elements after a delay, and so on. You could use angular animations for that (in order to be able to have control over the timing), and the best way to avoid some lag on these animations would be to use the ionViewDidEnter hook. This also will allow you to make the user feel like the animations of the elements within that page are a continuation of the transition of the page itself.


You can take a look at the NavControllerBase code:

1) IonViewWillEnter

// around line 666...
_transitionStart(...): Promise<NavResult> {

    // ...

    // around line 700...

    // create a callback that needs to run within zone
    // that will fire off the willEnter/Leave lifecycle events at the right time
    transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));

   // ...

}

And...

  // around line 805...
  _viewsWillLifecycles(enteringView: ViewController, leavingView: ViewController) {
    if (enteringView || leavingView) {
      this._zone.run(() => {
        // Here, the order is important. WillLeave must be called before WillEnter.
        leavingView && this._willLeave(leavingView, !enteringView);
        enteringView && this._willEnter(enteringView);
      });
    }
  }

If you inspect the beforeAddRead method from the animation.d.ts definition you'll see:

/**
* Add a function which contains DOM reads, which will run
* before the animation begins.
*/
beforeAddRead(domReadFn: Function): Animation;

So now we can be sure that the ionViewWillEnter lifecycle hook is executed before the page transition begins

2) IonViewDidEnter

This one is a little bit simpler. Again in the same NavControllerBase:

// around line 743...
  _transitionFinish(...): NavResult {

    // ...

    // around line 753...
    if (hasCompleted) {
      // transition has completed (went from 0 to 1)
      if (enteringView) {
        enteringName = enteringView.name;
        this._didEnter(enteringView);
      }

      // ..

    }

    // ...

  }

And

// around line 939...
  _didEnter(view: ViewController) {
    assert(this.isTransitioning(), 'nav controller should be transitioning');
    assert(NgZone.isInAngularZone(), 'callback should be zoned');

    try {
      view._didEnter();
      this.viewDidEnter.emit(view);
      this._app.viewDidEnter.emit(view);
    } catch (e) {
      this._errHandler && this._errHandler.handleError(e);
    }
  }

So because of that, we can say that the ionViewDidEnterlifecycle hook is triggered after the transition finishes.