Skip to content

Instantly share code, notes, and snippets.

@LayZeeDK
Last active March 20, 2023 10:26
Show Gist options
  • Save LayZeeDK/591cf484ea76f5370ecf27c49ccd40c6 to your computer and use it in GitHub Desktop.
Save LayZeeDK/591cf484ea76f5370ecf27c49ccd40c6 to your computer and use it in GitHub Desktop.
Router Store notes

Router Store notes

Analysis

Findings

NavigationError

Resets the URL to what it was before the navigation that caused an error. No new navigation is triggered.

URL update strategy

urlUpdateStrategy

  • 'deferred' (the default) updates the browser URL after successful navigation.
  • 'eager' updates the browser URL at the beginning of navigation. Updating the URL early allows you to handle a failure of navigation by showing an error message with the URL that failed.

To be determined

NavigationCancel

  • What is the URL after each of the NavigationCancellationCode reasons?

Navigate if needed effect

Should we add a way to emit events to the router store?

Canceled navigation resolution

canceledNavigationResolution

Same URL navigation

onSameUrlNavigation

Param inheritance strategy

paramsInheritanceStrategy

Router events

Order of router events

Navigation

  1. NavigationStart
  2. RoutesRecognized
  3. Route guards and route resolvers
  4. Route activated or the router state is rolled back to match the previous route
  5. NavigationEnd or NavigationCancel or NavigationError

Skipped navigation

  1. NavigationSkipped

Reasons for router events

NavigationCancel

NavigationCancel#code:

  • NavigationCancellationCode.GuardRejected: A navigation failed because a guard returned false.
  • NavigationCancellationCode.NoDataFromResolver: A navigation failed because one of the resolvers completed without emitting a value.
  • NavigationCancellationCode.Redirect: A navigation failed because a guard returned a UrlTree to redirect.
  • NavigationCancellationCode.SupersededByNewNavigation: A navigation failed because a more recent navigation started.
    NavigationCancel { id: 3, url: "/company", reason: "Navigation ID 3 is not equal to the current navigation id 4" }

NavigationError

  • Invalid route path
    NavigationError(id: 3, url: '/an-invalid/path', error: Error: Cannot match any routes. URL Segment: 'an-invalid/path')
  • Route resolver throws
  • Route matcher throws
  • Routed component throws in constructor (or a lifecycle hook?)
  • Lazy route chunk file is not found (bundles updated and the user needs to refresh)
    RouterTestingModule.withRoutes([
      {
        path: 'stale-chunk',
        loadChildren: () =>
          Promise.reject({ name: 'ChunkLoadError', message: 'ChunkLoadError' }),
          // or () => { throw { name: 'ChunkLoadError', message: 'ChunkLoadError' }; }
      },
    ]),

NavigationSkipped

  • location change to unsupported URL. The UrlHandlingStrategy cannot process the current or the target URL.
  • onSameUrlNavigation is set to ignore (the default) and the target URL is the same as the current URL.

Actions

Order of actions

Success case with early Navigation Action Timing

the default

  1. RouterRequestAction
  2. RouterNavigationAction
  3. Route guards and route resolvers
  4. Route activated
  5. RouterNavigatedAction

Success case with late Navigation Action Timing

  1. RouterRequestAction
  2. Route guards and route resolvers
  3. Route activated
  4. RouterNavigationAction
  5. RouterNavigatedAction

Error / Cancel case with early Navigation Action Timing

the default

  1. RouterRequestAction
  2. RouterNavigationAction
  3. Route guards and route resolvers
  4. The router state is rolled back to match the previous route
  5. RouterCancelAction or RouterErrorAction

Error / Cancel case with late Navigation Action Timing

  1. RouterRequestAction
  2. Route guards and route resolvers
  3. The router state is rolled back to match the previous route
  4. RouterCancelAction or RouterErrorAction

Action specifications

RouterRequestAction

Trigger: NavigationStart

Conditions:

  • Trigger is caused by router navigation

Payload:

  • FullRouterSerializer: { event: NavigationStart }
  • MinimalRouterSerializer: { event: { id, url, urlAfterRedirects: undefined } }

RouterNavigationAction

Trigger:

  • Early Navigation Action Timing: RoutesRecognized
  • Late Navigation Action Timing: NavigationEnd (just before the RouterNavigatedAction)

Conditions:

  • Trigger is caused by router navigation

Payload:

  • FullRouterSerializer:
{
  routerState: serialize(event)
  event: new RoutesRecognized(event.id, event.url, event.urlAfterRedirects, serialize(event))
}
  • MinimalRouterSerializer:
{ routerState, event: { id, url, urlAfterRedirects } }

RouterCancelAction

Trigger: NavigationCancel

Payload:

  • FullRouterSerializer:
{ storeState, event: NavigationCancel }
  • MinimalRouterSerializer:
{ storeState, event: { id, url, urlAfterRedirects: undefined } }

RouterErrorAction

Trigger: NavigationError

Payload:

  • FullRouterSerializer:
{
  storeState,
  event: new NavigationError(event.id, event.url, event.toString())
}
  • MinimalRouterSerializer:
{ storeState, event: { id, url, urlAfterRedirects: undefined } }

RouterNavigatedAction

Trigger: NavigationEnd

Payload:

  • FullRouterSerializer:
{
  routerState: serialize(event),
  event: NavigationEnd
}
  • MinimalRouterSerializer:
{
  routerState: serialize(event),
  event: { id, url, urlAfterRedirects }
}

Side effects

Serialize routerState

Trigger: NavigationStart

Conditions:

  • Trigger is caused by router navigation

Effect: RouterStateSerializer#serialize(router.routerState.snapshot)

Forward storeState to RouterCancel and RouterError payloads

Trigger: NavigationStart

Conditions:

  • Trigger is caused by router navigation

Effect: Update storeState

Navigate if needed

Trigger: Serialized router state snapshot { root: ActivatedRouteSnapshot + url: string } and/or navigation ID change

Conditions:

  • Snapshot isn't null or undefined
  • Trigger isn't router navigation, that is state hydration somehow. This would probably not happen without actions that anyone can dispatch.
  • Previous router event isn't a NavigationStart
  • Router#url isn't the same as the snapshot URL

Effect: Router#navigateByUrl(snapshot.url)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment