Router behavior when route reuse strategy is being used with nested routes
- Vorherrschende Sprache
- TypeScript
- Sterne
- 101k
- Forks
- 27.5k
- Ø Merge
- 1 T. 19 Std.
- Gemergte PRs (30 T.)
- 288
Beschreibung
### Which @angular/* package(s) are the source of the bug?
router
### Is this a regression?
No
### Description
Lets say app uses `FooComponent` and `AbcComponent` and defines routing as follows:
```ts
export const routes: Routes = [
{
path: 'Foo', data: {path: '/Foo - root'}, children:
[
{path: '', pathMatch: "full", component: FooComponent, data: {path: '/Foo - empty'}},
{path: 'Bar', data: {path: '/Foo/Bar - root'}, children: [
{path: '', pathMatch: "full", component: FooComponent, data: {path: '/Foo/Bar - empty'}},
{path: 'Baz', component: FooComponent, data: {path: '/Foo/Bar/Baz'}},
]},
],
},
{path: 'Abc', component: AbcComponent},
{path: '**', redirectTo: '/Foo'}
];
```
Also app is utilising route reuse strategy to reuse component whenever source and destination route both ends up on `FooComponent` like so:
```ts
export class FooRouteReuseStrategy extends BaseRouteReuseStrategy {
override shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
let futureChild = this.getChildDeep(future);
let currentChild = this.getChildDeep(curr);
if (futureChild.component === FooComponent && currentChild.component === FooComponent){
console.log('shouldReuse: true');
return true;
}
let reuse = super.shouldReuseRoute(future, curr);
console.log('shouldReuse: ', reuse);
return reuse;
}
private getChildDeep(route: ActivatedRouteSnapshot) {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}
}
```
It seems that in some cases angular router does not properly handle component reuse.
I have attached sample repository with minimal replication. Applications logs this specific events:
Foo component creation, Foo component destruction, Every call to `shouldReuseRoute` with returned value.
In some cases router destroys FooComponent despite shouldReuseRoute returns true and in never recreates them back.
To replicate this specific error please launch attached application from repository and navigate to http://localhost:4200/Foo.
When you start your application this way and navigate through the /Foo router subtree everything is working as expected, route is reused there is only one Foo Created in console.
When you navigate to Abc route Foo is destroyed since it is not supposed to be reused which is expected at this time.
After navigating to Abc when you navigate back to Foo/Bar/Baz component is recreated which is expected.
Then if you navigate to /Foo the problem manifests.
Angular calls RouteReuseStrategy to check if it should reuse route, strategy returns true. **Despite that** angular destroys FooComponent and never creates new instance of FooComponent.
So the replication goes like that:
1. Start the app, run browser on http://localhost:4200/Foo
2. Navigate to Abc route through link
3. Navigate to either Bar or Bar/Baz links through link
4. Navigate to Root link by url
Curiously when you skip point 3. app works normally.
When you start the app from url http://localhost:4200/Abc and go through the steps 3 - 4 it can be reproduced also.
I don't know if it is connected to this issue or I should issue another ticket, but there seems to be a problem with `activatedRoute.data` emissions in attached project.
`FooComponent` is displaying activatedRoute.data in its body.
If you start the application from url `http://localhost:4200/Foo/Bar/Baz` it shows `{ "path": "/Foo/Bar/Baz" }` but if you start the app form url `http://localhost:4200/Foo` and navigate to `http://localhost:4200/Foo/Bar/Baz` by link it shows `{ "path": "/Foo/Bar - root" }`. It is inconsistent and seems buggy. I am not sure if it supposed to work that way.
### Please provide a link to a minimal reproduction of the bug
https://github.com/MateuszBogdan/angular-router-bug
### Please provide the exception or error you saw
_No response_
### Please provide the environment you discovered this bug in (run `ng version`)
```true
Angular CLI: 18.2.6
Node: 20.14.0
Package Manager: npm 9.8.1
OS: win32 x64
Angular: 18.2.6
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1802.6
@angular-devkit/build-angular 18.2.6
@angular-devkit/core 18.2.6
@angular-devkit/schematics 18.2.6
@schematics/angular 18.2.6
rxjs 7.8.1
typescript 5.5.4
zone.js 0.14.10
```
### Anything else?
_No response_
Beitragsleitfaden
Rechercherichtung
Beginne mit dem Repository für die minimale Reproduktion und reproduziere die dokumentierte Navigationssequenz: /Foo, Abc, Bar oder Bar/Baz, dann /Foo. Verfolge die Entscheidungen von Angulars Router RouteReuseStrategy, die Erstellung und Zerstörung von FooComponent sowie die Emissionen von activatedRoute.data. Als abgeschlossen gilt, dass die Entscheidung zur Routenwiederverwendung eingehalten wird, ohne FooComponent zu verlieren, und dass das Datenverhalten konsistent ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- angular, typescript
- Bereich
- frontend, web-dev
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100