Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[error] Cannot reattach ActivatedRouteSnapshot created from a different route #1

Open
michalstepien opened this issue Dec 3, 2016 · 5 comments

Comments

@michalstepien
Copy link

Reproduce: click "Book a flight", next tab "Search Passengers", next "Your Bookings" in main tab, next "Book a flight".

Full error:
Error: Cannot reattach ActivatedRouteSnapshot created from a different route
at setFutureSnapshotsOfActivatedRoutes (http://localhost:8080/dist/vendor.js:78098:15) [angular]
at setFutureSnapshotsOfActivatedRoutes (http://localhost:8080/dist/vendor.js:78105:9) [angular]
at setFutureSnapshotsOfActivatedRoutes (http://localhost:8080/dist/vendor.js:78105:9) [angular]
at createNode (http://localhost:8080/dist/vendor.js:78082:9) [angular]
at http://localhost:8080/dist/vendor.js:78122:16 [angular]
at Array.map (native) [angular]
at createOrReuseChildren (http://localhost:8080/dist/vendor.js:78115:26) [angular]
at createNode (http://localhost:8080/dist/vendor.js:78077:41) [angular]
at createRouterState (http://localhost:8080/dist/vendor.js:78063:33) [angular]
at MapSubscriber.project (http://localhost:8080/dist/vendor.js:22991:153) [angular]
at MapSubscriber._next (http://localhost:8080/dist/vendor.js:13894:35) [angular]
at MapSubscriber.Subscriber.next (http://localhost:8080/dist/vendor.js:577:18) [angular]
at MergeMapSubscriber.notifyNext (http://localhost:8080/dist/vendor.js:16867:30) [angular]
at InnerSubscriber._next (http://localhost:8080/dist/vendor.js:83620:21) [angular]

@christianacca
Copy link

I think this issue might be solved by 6ac43c7

However, I don't think the CustomReuseStrategy as of writing will work with auxiliary routes.

I have experimented with this CustomReuseStrategy in an app that does have auxiliary routes and got the error:

Error: Cannot reattach ActivatedRouteSnapshot with a different number of children
  at setFutureSnapshotsOfActivatedRoutes

@parak80
Copy link

parak80 commented May 3, 2018

Hey, Ive got the same issue and that #CustomReuseStrategy did not work for me. Have you found any other solution?

@parak80
Copy link

parak80 commented May 3, 2018

Problem is when I go to the documents details and back to cases and cases detail it give me that same error and is not routing to the details. However if I refresh the page it work work. depends on with which click you start, the second wont go to the related path.
Here is my app.routing.module codes:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes, RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router';

const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'documents',
loadChildren: 'app/documents/documents.module#DocumentsModule'
},
{
path: 'cases',
loadChildren: 'app/cases/cases.module#CasesModule'
}
];

// This impl. bases upon one that can be found in the router's test cases.
export class CustomRouteReuseStrategy implements RouteReuseStrategy {

handlers: {[key: string]: DetachedRouteHandle} = {};

shouldDetach(route: ActivatedRouteSnapshot): boolean {
console.log('CustomRouteReuseStrategy:shouldDetach', route);
return true;
}

store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
console.log('CustomRouteReuseStrategy:store', route, handle);
this.handlers[route.routeConfig.path] = handle;
}

shouldAttach(route: ActivatedRouteSnapshot): boolean {
console.log('CustomRouteReuseStrategy:shouldAttach', route);
return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
}

retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
console.log('CustomRouteReuseStrategy:retrieve', route);
if (!route.routeConfig) {
return null;

  }
   return this.handlers[route.routeConfig.path];

}

shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.log('CustomRouteReuseStrategy:shouldReuseRoute', future, curr);
return future.routeConfig === curr.routeConfig;
}
}

@NgModule({
imports: [RouterModule.forRoot(routes /, { enableTracing: true }/)],
exports: [RouterModule],
providers: [
{provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy}
]
})

export class AppRoutingModule { }

@kavi87
Copy link

kavi87 commented May 18, 2018

When a component have a secondary outlet, its route.routeConfig property seems to always be null in my case and I don't know why. This fail in the setFutureSnapshotsOfActivatedRoutes method of the router.

function setFutureSnapshotsOfActivatedRoutes(curr, result) {
    if (curr.value.routeConfig /* <- This is null */ !== result.value.routeConfig) {
        throw new Error('Cannot reattach ActivatedRouteSnapshot created from a different route');
    }
    if (curr.children.length !== result.children.length) {
        throw new Error('Cannot reattach ActivatedRouteSnapshot with a different number of children');
    }
    result.value._futureSnapshot = curr.value;
    for (var /** @type {?} */ i = 0; i < curr.children.length; ++i) {
        setFutureSnapshotsOfActivatedRoutes(curr.children[i], result.children[i]);
    }
}

As @christianacca said, even if that first check passes, there would still be a problem with the children.length thing.

For me the best solution to all these problems would simply be to let people opt out of the destruction of components in the first place. "Oh no ! Memory leaks ! Performance !". So what ? This is the developer problem. Here it's not. You spend time doing routes, multiple outlets etc (which is awesome btw) but then simple requirements like keeping all the state that the user has changed is impossible.

And no, using a service to keep state would be an absolute nightmare to maintain because every little change would need to be tracked. The state of the view is not entirely determined by the final state of a model. If I have a search filter, it is not sufficient to put back the search query in the field when the user route back, I need to perform a search again. That is absolutely not maintainable. The user wants its view in the exact same state when he comes back, even the most obscure collapsible div in the corner, otherwise it is not good in my opinion, it is unprofessional.

@vahidvdn
Copy link

@christianacca I have the same issue. Did you find any workaround?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants