angular-ui / ui-router

The de-facto solution to flexible routing with nested views in AngularJS
http://ui-router.github.io/
MIT License
13.53k stars 3k forks source link

TransitionRejection error on load using v1.0.0-beta.3, no error using stable 0.3.1 #3118

Closed tyronedougherty closed 7 years ago

tyronedougherty commented 7 years ago

For some reason I am getting the following error on load and cannot for the life of me figure out why.

TransitionRejection(type: 2, message: The transition has been superseded by a different transition, detail: Transition#1( ''{} -> 'login'{} ))

This error does not appear using angular-ui-router version 0.3.1 (through bower), which leads me to suspect this is a bug.

Anyone know a solution to or any further information on the issue?

EDIT: Error also does not occur on the following versions:

It starts occurring in v1.0.0-beta.1, so I suspect a bug was introduced here. Anyone have further info on this?

christopherthielen commented 7 years ago

You were seeing the default error handler code described in the migration guide: https://ui-router.github.io/guide/ng1/migrate-to-1_0

The initial transition is triggered by url synchronization. You probably have a state change start handler that transitions to login. The second transition supersedes the first one, and that is the error that is being blond the Console

You can turn off this default error handler as described in the guide and docs, or you can migrate to a 1.0 transition hook (using a redirect), which does not trigger the superseded error.

Here's an example: https://github.com/ui-router/sample-app-ng1/blob/master/app/global/requiresAuth.hook.js#L22

tyronedougherty commented 7 years ago

This explains a lot, thank you so much @christopherthielen ! 😄

tyronedougherty commented 7 years ago

@christopherthielen just an update, I was about to implement the transition hooks as described for the transition to the login screen when not logged in, but first I removed my $stateChangeStart event handler just to check that it was the issue and I still received an error. There is nothing changing my state on initialization that I can find.

This is the error:

TransitionRejection(type: 2, message: The transition has been superseded by a different transition, detail: Transition#1( ''{} -> 'overview'{} ))
http://localhost:8086/lib-custom/angular-ui-router-1.0.0-beta.3.min.js
Line 9

No matter what route I go to, I still get the same error. If I'm reading that correctly, it seems like some sort of empty state(?) is transitioning to my overview state and failing, however I do still end up on whatever route/state I request, so I'm not sure if there's an issue other than an error on load. Changing routes (e.g. by clicking a link) does not throw the error, it only happens on page load.

Got any idea as to what could be going on here?

Many thanks, appreciate your help on this!

christopherthielen commented 7 years ago

turn on tracing, as described here: https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-change-events for more details about transitions

tyronedougherty commented 7 years ago

It seems I located the source of the issue, a little bit of legacy code hidden away :(

I have now successfully implemented the transition hooks as described in the docs you linked above with one exception, the $transitions.onStart method will still throw the TransitionRejection error when returning the trans.router.stateService.target, instead it should use the onBefore method described here.

For anyone stumbling on this issue later, my final authentication redirect code works like a charm:

//Redirect to login if not authenticated before any transition
  $transitions.onBefore({
    to: function (state) {
      return state.name !== 'login';
    }
  }, function (trans) {
    if (!authenticationService.loadLocalCredentials()) {
      return trans.router.stateService.target('login');
    }
  });

Many thanks to you @christopherthielen !! Much appreciated 😄

christopherthielen commented 7 years ago

@tyronedougherty I'm glad you got it working. I am surprised you had to use onBefore though, onStart should work basically the same way.

To address to some of your comments:

This is the error: ... different transition, detail: Transition#1( ''{} -> 'overview'{} ))

This logged output indicates transition # 1. Since transitions start at # 0, there must've been one earlier transition started. I was hoping the output from $trace would help with this.

If I'm reading that correctly, it seems like some sort of empty state(?) is transitioning to my overview state and failing

There is indeed an "empty state". It is the implicit root state. When the app bootstraps, the router starts with this implicit root state active. The initial transition goes from the root state to your initial state.

is transitioning to my overview state and failing, however I do still end up on whatever route/state I request

The transition superseded message logs the newer transition, which is the one that succeds.