Эффекты ngrx: вывод не добавляется в поток действий

Проблема может быть повторно вызвана в этот stackblitz.

Пример прост: пользователь выбирает расу и специальность.

Я хочу, чтобы при выборе расы специальность сбрасывалась (ред?).

Для этого я создал эффект:

@Effect()
raceChange = this.actions
  .pipe(
    ofType(SET_RACE),
    mapTo(new SetSpecialtyAction(''))
  );

Но действие не добавляется в поток. Может кто-нибудь объяснить мне, почему? (Я новичок в @ngrx, поэтому будьте внимательны!)

PS: Я знаю, что могу использовать решение из моего предыдущего вопроса, но я пытаюсь изучить основы ngrx.

код для компонента stackblitz:

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.raceStore.select('race');
  currentSpecialty = this.specStore.select('specialty');

  constructor(
    public raceStore: Store<RaceState>,
    public specStore: Store<SpecialtyState>,
    ) {
      this.currentRace.subscribe(x => console.info('race : ', x));
      this.currentSpecialty.subscribe(x => console.info('spec : ', x))
    }

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

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


export const SET_RACE = '[RACE] Set';
export 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 RaceState {
  readonly race: string;
}

export interface SpecialtyState {
  readonly specialty: string;
}
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
511
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

mapTo отображает излучение в строку, используя map, чтобы отобразить действие, которое будет отправлено.

Чтобы ваш пример работал, я изменил две вещи:

1- замените mapTo на map в эффекте:

@Effect()
raceChange = this.actions
   .pipe(
     ofType(SET_RACE),
     map(() => new SetSpecialtyAction(''))
);

2- Измените редуктор, который игнорировал пустые значения:

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

const value = '' || 'Not Empty';
console.info(value);

Вот рабочая вилка.

Вы также можете сопоставить несколько действий, используя switchMap и возвращая массив fo actions:

@Effect()
raceChange = this.actions
   .pipe(
     ofType(SET_RACE),
     switchMap(() => [new SetSpecialtyAction(''), ...])
);

Черт побери, я совсем забыл, что игнорирую пустые значения! Одно это решило мою проблему. Принимаю во внимание ваши замечания по поводу mapTo и switchMap, спасибо! Быстрый вопрос, если вы знаете, как: учитывая, что у меня есть два действия, как я могу испустить SetRaceAction в своем эффекте без запуска бесконечного цикла? Нужно ли мне для этого создавать новое состояние?

user4676340 26.09.2018 14:36

Технически у вас может быть фильтр в конвейере эффектов RxJs, чтобы предотвратить бесконечный цикл. Но я бы избегал эффектов, которые могут запускать друг друга.

ibenjelloun 26.09.2018 14:44

Нет необходимости в эффекте, вы можете прослушивать гонку внутри специального редуктора:

export function specialtyReducer(state: string = undefined, action: SetSpecialtyAction | SetRaceAction): string {
  switch(action.type) {
    case SET_RACE:
      return '';
    default:
     return action.specialty || state;
  }
}

Я сказал, что это именно то, что я уже использую, и я не хочу использовать, потому что я изучаю эффекты.

user4676340 26.09.2018 14:27

Я хочу немного защитить свой ответ здесь, потому что вы этого не сказали и не используете решение, которое я написал здесь. Если вы хотите изучить эффекты, вы также должны знать, когда использовать эффекты, а когда нет. Этот случай на самом деле не «вызывает» побочный эффект, а просто изменяет состояние, что делает его подходящим для использования редукторов. Кроме того, принятый ответ может вызвать проблемы позже, когда вы введете дополнительные действия, потому что редуктор всегда будет очищать состояние, когда в действии нет specialty.

timdeschryver 26.09.2018 14:41

Это минимальный воспроизводимый пример, а не реальный случай. Я пытаюсь понять, как работают эффекты и что они делают. Благодаря принятому ответу, теперь верю. Я неявно сказал, что использую это решение, которое связано в моем вопросе, которое вы, по-видимому, вообще не читали. Ваш ответ хорош, не поймите меня неправильно, я ничего не имею против: моя проблема в том, что вы полностью проигнорировали контекст вопроса и фактически создали дубликат. Этот вопрос касался того, что эффекты не работают (потому что я сделал что-то глупое), а не о том, какое решение лучше всего использовать.

user4676340 26.09.2018 14:45

: thumbsup: Наверное, я неправильно понял твой вопрос.

timdeschryver 26.09.2018 15:11

Другие вопросы по теме