Skip to content
Open
50 changes: 48 additions & 2 deletions packages/vue-router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const createIonRouter = (
direction: undefined,
action: undefined,
delta: undefined,
to: undefined,
};

/**
Expand All @@ -46,7 +47,45 @@ export const createIonRouter = (
_: RouteLocationNormalized,
failure?: NavigationFailure | void
) => {
if (failure) return;
if (failure) {
/*
* State staged for a navigation that failed describes something that
* did not happen. handleHistoryChange normally consumes it, but it does
* not run when the navigation fails, so it has to be cleared here or
* the next navigation picks it up instead.
*
* A stale delta makes that navigation look like history traversal,
* which stops the incoming route from being added. Stale route params
* are left behind by handleNavigateBack and apply the previous route's
* id and pop action to whatever is navigated to next.
*
* Only clear state that belongs to this navigation. A second history
* navigation can replace this one and stage its own information first,
* in which case clearing would strip the delta from the navigation that
* is still running.
*
* This only covers navigations that fail. A guard that returns a
* location redirects rather than fails, so vue-router neither reverts
* the history entry nor calls afterEach for the original navigation,
* and the staged state still reaches the redirect target.
*/
const staysWithThisNavigation =
currentNavigationInfo.to === undefined ||
currentNavigationInfo.to === to.fullPath;

if (staysWithThisNavigation) {
currentNavigationInfo = {
direction: undefined,
action: undefined,
delta: undefined,
to: undefined,
};

incomingRouteParams = undefined;
}

return;
}

const { direction, action, delta } = currentNavigationInfo;

Expand All @@ -68,6 +107,7 @@ export const createIonRouter = (
direction: undefined,
action: undefined,
delta: undefined,
to: undefined,
};
}
);
Expand Down Expand Up @@ -101,7 +141,7 @@ export const createIonRouter = (
});
}

opts.history.listen((_: any, _x: any, info: any) => {
opts.history.listen((to: any, _x: any, info: any) => {
/**
* history.listen only fires on certain
* event such as when the user clicks the
Expand All @@ -123,6 +163,12 @@ export const createIonRouter = (
*/
action: info.type === "pop" && info.delta >= 1 ? "push" : info.type,
direction: info.direction === "" ? "forward" : info.direction,

/**
* Recorded so that a failed navigation can tell whether this
* information is its own before clearing it.
*/
to,
};
});

Expand Down
6 changes: 6 additions & 0 deletions packages/vue-router/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,10 @@ export interface NavigationInformation {
action?: RouteAction;
direction?: RouteDirection;
delta?: number;
/**
* The location the browser moved to when this information was staged. Used to
* tell whether the information belongs to a particular navigation, since a
* second history navigation can stage its own before the first one settles.
*/
to?: string;
}
Loading
Loading