2017-02-12 3 views
1

Я проникаю использовать ngrx эффекты и у меня есть следующий вопрос: так как dispatch возвращается void Я не знаю, как предотвратить маршрутизатор навигации, если ошибка происходит от моего Эффект ngrx (например, от this.userAccountService.updateFirstName(...).Предотвращение маршрутизатора навигации в случае выхода из строя эффекта/ошибка

Из моего класса компонента:

updateFirstName() { 
    this.formStatus.submitted = true; 
    if (this.formStatus.form.valid) { 
     //Dispatch from the store 
     this.store.dispatch(new UpdateFirstNameAction(this.formStatus.form.value.firstName)); 
     //Undesired behavior: will navigate even in case of error/failure! 
     this.router.navigate(['/dashboard/useraccount']); 
    } 
    } 

Из моего класса эффекта:

@Effect() 
    updateFirstName$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME) 
    .map((action: UpdateFirstNameAction) => action.payload) 
    .switchMap(firstName => 
     this.userAccountService 
     .updateFirstName(firstName) 
     .map(() => new UpdateFirstNameSuccessAction(firstName)) 
     //I obviously can't navigate from here 
    ); 

Я не уверен, что это хорошая практика (или даже возможно) использовать маршрутизатор для навигации от эффекта.

Может кто-нибудь предложить чистое решение, чтобы предотвратить навигацию маршрутизатора в случае ошибки, возникающей из-за моего эффекта?

+0

UpdateFirstNameSuccessAction должен установитьFirstNameSuccess = true, , а затем, подписавшись на него, получите значение, и если да, перейдите на страницу. –

+0

Привет @ShlomiLevi, тогда я бы представил новое состояние. Не так ли? – balteo

+0

в двух словах, вы должны отреагировать на сохранение изменений. :) Нет необходимости иметь новое состояние, просто создайте свое состояние для поддержки измененного поля. Это потому, что ваш магазин должен иметь состояние, а когда вы отправляете действие, вы в основном меняете магазин. поэтому после того, как вы меняете магазин, вы подписываетесь на поле, которое изменилось, и из-за этого вы реагируете с тем, что вам нужно :) –

ответ

1

Я бы предложил использовать модуль @ngrx/router-store. С его помощью вы можете создавать действия маршрутизации и, используя его, у вас есть несколько вариантов.

Вы можете испустить несколько действий из одного эффекта. Таким образом, ваш эффект может использовать concatMap испускать два действия: ваши действия успеха и действие маршрутизации (созданное с создателем go действия):

import { go } from '@ngrx/router-store'; 
import 'rxjs/add/operator/concatMap'; 

@Effect() 
updateFirstName$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME) 
    .map((action: UpdateFirstNameAction) => action.payload) 
    .switchMap(firstName => this.userAccountService 
    .updateFirstName(firstName) 
    .concatMap(() => [ 
     new UpdateFirstNameSuccessAction(firstName), 
     go(['/dashboard/useraccount']) 
    ]) 
); 

Однако, вы можете также рассмотреть возможность использования отдельного эффекта, который управляет только маршрутизация:

import { go } from '@ngrx/router-store'; 
import 'rxjs/add/operator/mapTo'; 

@Effect() 
updateFirstRouting$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS) 
    .mapTo(go(['/dashboard/useraccount']); 

Другим важным моментом является то, что один эффект может ответить на несколько действий, чтобы вы могли использовать таблицу простых отображений действия типа на маршруте, чтобы сделать что-то вроде этого:

import { go } from '@ngrx/router-store'; 
import 'rxjs/add/operator/filter'; 
import 'rxjs/add/operator/map'; 

simpleRoutes: { [type: string]: string } = { 
    [currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS]: '/dashboard/useraccount' 
}; 

@Effect() 
simpleRouting$: Observable<Action> = this.actions$ 
    .map((action) => this.simpleRoutes[action.type]) 
    .filter(Boolean) 
    .map((route) => go([route])); 

Какой бы вариант вы ни выбрали, использование действий маршрутизации для навигации, инициированное внутри эффектов, делает вещи более легко проверяемыми. Легко написать тесты эффектов, чтобы гарантировать, что, когда эффект получает определенное действие, он испускает соответствующее действие.Более подробная информация о результатах тестирования here.

+0

Большое спасибо Cartant. Мне больше нравится отдельный эффект, который управляет только маршрутизацией. У меня все еще есть один опрос: это решение вводит связь между «ActionTypes.UPDATE_FIRST_NAME_SUCCESS» и маршрутизацией? Есть ли способ избежать этой связи? – balteo

+1

Если вы всегда хотите, чтобы действие переходило к определенному маршруту, я не вижу, как проблема будет проблемой. Похоже, у вас есть ситуация, когда вы можете или не хотите перемещаться. Я обновил ответ с помощью другого варианта. Обратите внимание, что он может быть расширен для использования динамической таблицы, которая может быть настроена через службу, в которой хранятся эффекты. Поэтому перед отправкой действия UPDATE_FIRST_NAME_SUCCESS вы можете настроить сопоставление действий к маршруту. Возможно, что-то подобное ближе к тому, что вы ищете. – cartant

+0

Спасибо. Последнее решение является приятным и гибким. – balteo

0

Вы можете сделать это двумя способами.

  1. С помощью эффектов ухватите действие УСПЕХА, а затем перенаправьте.

    @Effect() someeffect $: Наблюдаемое = this.actions $ .ofType (currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS)
    .do (действие =>/* сделать перенаправление (action.payload) * /);

  2. С Подписка:

допустим это ваше состояние: { счет: { имя пользователя: пустой } }

Компонент:

var username$ = this.store.select(account => account.username); 

username$.subscribe(user => { 
    // the user have changed due to reducer who is getting the action with new user. 
    // do here redirect... 
}); 
+0

Большое спасибо. Еще один вопрос: есть ли причина, по которой вы «подписываетесь» из магазина, а не «выбираете» его? Также хорошо ли переходить от эффекта en, а не от компонента? – balteo

+0

вы приветствуете. Да, вы должны использовать 'select'. потому что он доставит вам кусочек из Магазина. Это просто быстрый и грязный ответ ..;) Лучше перенаправить из эффектов, потому что это ваш BL. Я имею в виду, что вы можете применить или удалить эффект по вашему выбору. в некоторых случаях вы перенаправляете, а в других случаях делаете что-то еще. поэтому все, что вам нужно сделать, применить/удалить эффект динамический. –

Смежные вопросы