ShaneK · GitHub

Issue number: internal


What is the current behavior?

Currently, prepareLazyLoaded in ion-tab sets loaded = true before it attempts the attach, and the try/catch wrapped around attachComponent is synchronous while attachComponent itself is async. So when the first attach rejects, the rejection skips the catch entirely and loaded is already true, which means the if (!this.loaded && ...) guard blocks every later attempt. The tab renders as an empty page for the rest of the session, even if whatever caused the failure is fixed.

ion-tabs activates a tab by setting active rather than by awaiting the tab's setActive(), so the failure goes through the @Watch('active') path. That call isn't awaited, so on rejection the error surfaces as an unhandled promise rejection and printIonError never runs. select() resolves successfully while the tab is blank, so there's no signal to the caller either.

What is the new behavior?

With this change, prepareLazyLoaded caches the in-flight attach promise instead of flipping a boolean up front. Concurrent activations still share a single attempt, which is what the old loaded = true ordering was providing, but the cache is only cleared when the attach rejects, so the next activation retries. The unawaited call in the active watcher now has a .catch that routes the error to printIonError, which is what the unreachable catch block was there for.

setActive() still rejects on a failed attach and still leaves active as false, so that part is unchanged.

Does this introduce a breaking change?

  • Yes
  • No

Other information

There's no stock test page that reproduces the failure, since it needs a delegate that rejects, but the tabs pages confirm normal lazy loading still works:

Read the original on github.com ↗