NgRx: отправка одного события из магазина в другое - PullRequest
0 голосов
/ 25 сентября 2018

Я начинаю использовать @ngrx и сталкиваюсь с проблемой, на которую не могу найти ответ.

Я проиллюстрировал это в этом стеке : когда игрок выбирает расу, специальность должна быть возвращена к неопределенной.

Сначала я подумал, что смогу использовать редуктор, но он не знает о магазине без инъекций.

Как мне решить эту проблему?
(Примечание: это воспроизводимый пример, я знаю, что могу добавить в свои функции вторую диспетчеризацию. Я хочу сделать это автоматически)

Код, связанный с кодом:

import { Component } from '@angular/core';
import { Store, Action, ActionReducerMap } from '@ngrx/store';

@Component({
  selector: 'my-app',
  template: 
`
<select #race (change)="dispatchRace(race.value)" placeholder="Select a race">
  <option value="Elf">Elf</option>  
  <option value="Orc">Orc</option>  
  <option value="Dwarf">Dwarf</option>
</select>

  <select #spec (change)="dispatchSpecialty(spec.value)" placeholder="Select a specialty">
  <option value="Warrior">Warrior</option>  
  <option value="Berzerkrer">Berzerkrer</option>  
  <option value="Healer">Healer</option>  
</select>

<p>
  Current race: {{ (currentRace | async) || 'None' }}
</p>
<p>
  Current Spec: {{ (currentSpecialty | async) || 'None' }}  
</p>  
`
})
export class AppComponent {

  currentRace = this.store.select('race');
  currentSpecialty = this.store.select('specialty');

  constructor(public store: Store<CharacterState>) { }

  dispatchRace(race) {
    this.store.dispatch(new SetRaceAction(race));
  }

  dispatchSpecialty(spec) {
    this.store.dispatch(new SetSpecialtyAction(spec));
  }
}


const SET_RACE = '[RACE] Set';
const SET_SPECIALTY = '[CLASS] Set';

export class SetRaceAction implements Action {
  readonly type = SET_RACE;
  constructor(public race: string) { }
}

export class SetSpecialtyAction implements Action {
  readonly type = SET_SPECIALTY;
  constructor(public specialty: string) { }
}

export function raceReducer(state: string = undefined, action: SetRaceAction): string {
  return action.race || state;
}

export function specialtyReducer(state: string = undefined, action: SetSpecialtyAction): string {
  return action.specialty || state;
}

export interface CharacterState {
  readonly race: string;
  readonly specialty: string;
}

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

Так что, если я правильно понимаю: вы хотите отправить одно действие, которое вызывает другое?

  1. это лучше всего делать с использованием эффектов NGRX .Ваш файл эффектов будет прослушивать действие и отправлять оба при обнаружении действия.(извините за фрагмент, у меня были проблемы с форматированием)

// make sure to import rxjs 6 correctly
import { map, switchMap, tap } from 'rxjs/operators';

@Effect()
twoActionEvent = this.actions$
    .ofType(appActions.FIRST_ACTION)
    .pipe(
        switchMap((action$: appActions.firstAction) => {
            return //what ever you need in the first action
        }),
        map((firstActionPayload) => {
            return {
               type: appActions.FIRST_ACTION_SUCCESS,
                payload: firstActionPayload
            }
         }),
         tap(() => {
             this.store.dispatch(new appActions.SecondAction(//payload))
         })
     );
constructor(private actions$: Actions,
            private store: Store<AppState>) {}
еще один способ сделать это - прослушать действие в вашем приложении, подписаться на свойство в вашем магазине и, когда это свойство имеет значение true: отправить второе действие
0 голосов
/ 25 сентября 2018

Я хотел добавить еще одно решение, которое я сделал в своих собственных реализациях, когда использую флаги в своем магазине.

просто измените флаг в вашем состоянии во время действия, которое вы отправляете, например:

import * as AppActions from './app.actions'; import * as handler from './app.models';

export function appReducer(
        state: handler.AppState = handler.initialAppState,
        action: AppActions.AppActions
    ) {
        switch(action.type) {
            case AppActions.SET_RACE_ACTION:
                return {
                    ...state,
                    race: action.payload
                    // set your flag in state
                    myFlag: undefined
                 }
       }

}

0 голосов
/ 25 сентября 2018

Если вы добавите console.log в raceReducer, вы увидите, что все действия выполняются всеми редукторами:

export function raceReducer(state: string = undefined, action: SetRaceAction): string {
  console.log(action);
  return action.race || state;
}

Вам просто нужно обработать SetRaceAction и SetSpecialtyActionпо-разному.

Редактирование стека блиц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...