Как исправить утечку подписки Angular ngrx store - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть приложение ponyracer, которое реализует магазин ngrx.Очень простой функционал: начать гонку, добавить пони, удалить пони, таблица результатов.Проблема возникает, когда я удаляю или добавляю пони - в основном эта функциональность относится к созданию или уничтожению компонента пони.Таким образом, любой добавленный Pony хранится где-то по какой-то причине, и даже после уничтожения компонента - приложение все еще имеет доступ ко всем добавленным и удаленным пони и выполняет их итерацию, например, когда мне нужно просмотреть оценки только для существующих пони - но все (даже ранееудалены) пони отображаются

Я использую store.select.pipe (...). subscribe (), и нет необходимости использовать onDestroy и 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>

Когда пони достигает финиша, действие отправляется, и пони добавляется в свойство хранилища под названием currentRaces, поэтому хранит треки, который пони закончил первым, а затем второй и т. Д.

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: []
}

Но это действиетакже отправляется для удаленных пони, и они также попадают в store.currentRaces и отображаются в таблице результатов.И я не могу понять, откуда эти убранные пони.Потому что state.races всегда актуальны и правильны (в соответствии с инструментами redux dev), а races.component принимает state.races для отображения вида для каждого пони, и он всегда корректен и свеж:

movePony() {
    some code for moving a pony
      if(ponyReachedFinish) {
      this.store.dispatch(new PonyRacerActions.StopRace({name: this.race.name, place, points})
    }
}

Здесь выможно найти весь код, если требуется более подробная информация: https://github.com/joistick1/pr2

ОБНОВЛЕНИЕ: Проблема решена.Проблема возникла из-за утечки подписки, как я и предполагал изначально.Я применил OnDestroy и в этом методе применил одну строку кода this.subscription.unsubscribe ();

1 Ответ

0 голосов
/ 15 февраля 2019

В вашем редукторе, когда вы удаляете пони, вы напрямую изменяете состояние, а не возвращаете новое неизменное состояние.Попробуйте применить следующие изменения:

case PonyRacerActions.DELETE_PONY:
            return {
                ...state,
                races: state.races.filter(race => race != action.payload),
                currentRaces: []
            }
...