aurelia / router

A powerful client-side router.
MIT License
121 stars 115 forks source link

navigateToRoute does not update currentInstruction immediately #658

Open brandon-marginalunit opened 4 years ago

brandon-marginalunit commented 4 years ago
"aurelia-framework": "1.3.1",
"aurelia-router": "1.7.1",
this.router.navigateToRoute(
    this.router.currentInstruction.config.name, 
    { foo: "bar" },
    { replace: true }
);

console.log(this.router.currentInstruction.queryParams.foo); // undefined

At the time of this console.log(), the actual URL in the browser has been visibly updated. And the parameter does make it into currentInstruction eventually. But for some reason, router.currentInstruction does not get updated synchronously. This is causing havoc in my logic when I want to do non-destructive changes like the following:

/**
 * Apply one or more route params, keeping the current route 
 * and all other param values.
 */
export function assignRouteParams(router: Router, params: {[key: string]: any}) {
    if (router.currentInstruction != null) {
        router.navigateToRoute(
            router.currentInstruction.config.name ?? "unknown", 
            { ...router.currentInstruction.params, ...router.currentInstruction.queryParams, ...params },
            { replace: true }
        );
    }
}

Here, currentInstruction.queryParams cannot be relied upon to include any changes that have just been made to the params via navigateToRoute, which means things get lost.

Is this a bug? And if not, is there a workaround? I tried adding trigger: true to the options, to no effect.

brandon-marginalunit commented 4 years ago

Workaround for anyone else who's stuck on this bug, pushing the navigation instruction onto the event loop seems to work:

/**
 * Apply one or more route params, keeping the current route 
 * and all other param values.
 */
export function assignRouteParams(router: Router, params: {[key: string]: any}) {
    if (router.currentInstruction != null) {
        setTimeout(() =>
            router.navigateToRoute(
                router.currentInstruction.config.name ?? "unknown", 
                { ...router.currentInstruction.params, ...router.currentInstruction.queryParams, ...params },
                { replace: true }
            ), 0);
    }
}