I'm new to NgRx. After a bunch of reading, I added the router (@ngrx/router-store) to the app state to access the router parameter in the selector. I'm using a CustomRouterSerializer together with RouterState.Minimal. Since then I'm facing a problem which is when I'm navigating away from the detail page (/hero/:heroId) to list page (/) for example, the getSelectedHero selector from the detail page gets called which leads to other problems. Sure I can put null checks in...
But since I'm a beginner, I thought I'd better ask. It seems to be wrong that the getSelectedHero gets called on the transition to a different page. Sure the router state is changing, but?
I spent some time trying to find a solution that doesn't include an undefined check.
I created a "super" application that demonstrates the issue. I pushed it up to GitHub and to StackBlitz.
Here is the selector code from the detail page (/hero/:heroId) which gets called when navigating away from it.
export const getSelectedHero = createSelector(
selectHeroesState,
getRouteState,
(state, router) => {
const hero = state.entities[router.state.params.heroId];
// FixMe: simplifies the problem... hero is undefined if you navigation for /hero/:heroId to / and following line will throw an error.
console.log("getSelectedHero", hero, hero.id, hero.name);
return hero;
}
);
In the detail page (/hero/:heroId) I use the following:
public ngOnInit() {
this.hero$ = this.store.pipe(select(getSelectedHero));
}
The problem is that when you navigate to other routes the route parameter
:heroIdis not available.when you navigate to a hero page,
.../hero/2for example, the route param:heroIdis available, because you have defined the routehero/:heroId;When you navigate to the root page
.../the route matches"", and that causes the route param:heroIdnot to be set (it appears as undefined on your selector)Because your
getSelectedHerouses selector the route state selectorgetRouteState, every time there is a route change and the subscription underhero$is active, thegetSelectedHerowill be called.to resolve you could do:
Or you could move the selected heroId variable to the hero state, this way the navigation does not trigger the hero data selection