Router behavior when route reuse strategy is being used with nested routes
- Dominant language
- TypeScript
- Stars
- 101k
- Forks
- 27.5k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 288
Description
### 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_
Contributor guide
Research direction
Start with the minimal reproduction repository and reproduce the documented navigation sequence: /Foo, Abc, Bar or Bar/Baz, then /Foo. Trace Angular router RouteReuseStrategy decisions, FooComponent creation and destruction, and activatedRoute.data emissions. Done means the route reuse decision is respected without losing FooComponent and the data behavior is consistent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100