I have a ponyracer app, which implements ngrx store. Very basic functionality: start race, add pony, remove pony, table of scores. The issue comes when I remove or add pony - basically this functionality refers to creating or destroying a pony component. So any added Pony stores somewhere for some reason, and even after destroying a component - app still has an access to all added and deleted ponies, and iterates them for example when I need to view scores only for existing ponies - but all (even previously removed) ponies are shown
I use store.select.pipe(...).subscribe(), and there is no need to use onDestroy and unsubscribe()
races.component.ts
export class RacesComponent implements OnInit {
racesState: Observable<fromPonyRacer.State>;
constructor(private store: Store<fromApp.AppState>) { }
ngOnInit() {
this.racesState = this.store.select("raceList");
this.racesState.subscribe()
}
}
races.component.html
<pr-race *ngFor="let race of (racesState | async).races; let i = index"
[race]="race" [index]="i">
</pr-race>
race.component.ts
export class RaceComponent implements OnInit {
@Input() race: RaceModel;
@Input() index: number;
racesState: Observable<fromPonyRacer.State>;
constructor(private store: Store<fromApp.AppState>) { }
ngOnInit() {
this.racesState = this.store.select("raceList");
this.racesState.pipe(
tap(races => {
if(races.raceStatus) this.movePony();
})
)
.subscribe()
}
}
race.component.html
<div class="race">
<img class="pony-img" [src]="race.src">
</div>
When a pony reaches finish, action is dispatched and pony is added to the store property called currentRaces, so store tracks which pony finished first, which is second and so on.
const initialState: State = {
races: [
new RaceModel(some data),
new RaceModel(some another data),
new RaceModel(some more data)
],
raceStatus: false,
raceCount: 0,
isNewrace: false,
poniesAreAboutToFinish: null,
currentRaces: []
}
But this action is also dispatched for removed ponies, and they are also getting to the store.currentRaces and are shown in score table. And I cannot figure out where these removed ponies are coming from. Because state.races are always actual and correct (according to redux dev tools), and races.component takes state.races for rendering view for each pony, and it is always correct and fresh
movePony() {
some code for moving a pony
if(ponyReachedFinish) {
this.store.dispatch(new PonyRacerActions.StopRace({name: this.race.name, place, points})
}
}
Here you can find the whole code if more details are needed: https://github.com/joistick1/pr2
UPDATE: Issue solved. The problem occurred due subscription leak, as I assumed initially. I applied OnDestroy and in this method applied one line of code this.subscription.unsubscribe();
subscribeon hot observables, why is thatthere is no need to use onDestroy and unsubscribe()? This should be mandatory. - user4676340asyncpipe to subscribe, or explicitly call.unsubscribe()in your component. - Brandon