如何使用ngrx和效果订阅动作成功回调

时间:2017-04-05 09:08:36

标签: angular ngrx

我试图做一件简单的事 - 在保存一些实体后(使用http请求) 我想导航回列表路线。问题是:如何订阅成功动作(或者可能是减速器或效果?)

这是我的行为代码:

static SAVE_POST = '[POST] Save POST';
savePOST(Post): Action {
    return {
        type: PostActions.SAVE_POST,
        payload: Post
    };
}

static SAVE_POST_SUCCESS = '[POST] Save POST Success';
savePOSTSuccess(Post): Action {
    console.log('action: savePostSuccess')
    return {
        type: PostActions.SAVE_POST_SUCCESS,
        payload:Post
    };
}

我正在使用效果:

   @Effect() savePost$ = this.update$
    .ofType(PostActions.SAVE_POST)
    .map(action => action.payload)
    .switchMap(post => this.svc.savePost(post))
    .map(post => this.postActions.savePOSTSuccess(post));

减速器:

const initialState: PostListState = [];

export default function (state = initialState, action: Action): PostListState {
    switch (action.type) {
        case PostActions.LOAD_POST_SUCCESS: {
            return action.payload;
        }
        case PostActions.SAVE_POST_SUCCESS: {
            console.log('SavePOST SUCCESS',action.payload)
            let index = _.findIndex(state, {_id: action.payload._id});
            if (index >= 0) {
                return [
                    ...state.slice(0, index),
                    action.payload,
                    ...state.slice(index + 1)
                ];
            }
            return state;
        }
        default: {
            return state;
        }
    }
}

在我的组件中,我想订阅成功回调:

   handlePostUpdated($event) {
     this.post = this.code;
     let _post: Post = Object.assign({}, { _id: this.id, name: this.name, text: this.post });
     this.store.dispatch(this.postActions.savePOST(_post)); //not have "subscribe" method

  }

感谢您的帮助

6 个答案:

答案 0 :(得分:36)

您也可以订阅组件中的操作:

[...]
import { Actions } from '@ngrx/effects';
[...]

@Component(...)
class SomeComponent implements OnDestroy {
    destroyed$ = new Subject<boolean>();

    constructor(updates$: Actions) {
        updates$
            .ofType(PostActions.SAVE_POST_SUCCESS)
            .takeUntil(this.destroyed$)
            .do(() => /* hooray, success, show notification alert ect.. */)
            .subscribe();
    }

    ngOnDestroy() {
        this.destroyed$.next(true);
        this.destroyed$.complete();
    }
}

答案 1 :(得分:19)

基于此:https://netbasal.com/listening-for-actions-in-ngrx-store-a699206d2210进行了一些小修改,因为从ngrx 4开始,不再有Dispatcher,而是ActionsSubject

import { ActionsSubject } from '@ngrx/store';

subsc = new Subcription();

constructor(private actionsSubj: ActionsSubject, ....) { 
  this.subsc = actionsSubject.subscribe(data => { 
     if(data.type === 'SAVE_POST_SUCCESS') {
       // do something...
     }
  });
}

ngOnDestroy() {
  this.subsc.unsubscribe();
}

答案 2 :(得分:2)

你需要有一个选择器,为你提供最新的帖子

this.latestPost$ = this.store.select(fromRoot.getPost);

然后您可以订阅this.latestPost$ observable并重定向到您的新路线,假设您已在组件中声明latestPost$: Observable<Post>;

有关详细信息,请参阅此示例应用https://github.com/ngrx/example-app

答案 3 :(得分:1)

如果您还添加了reducer功能代码并在savePOSTSuccess操作中显示保存的帖子如何影响您的状态,那会更好。

通常,您可以在帖子状态中放置“编辑”布尔属性。

在reducer上,您可以通过将属性设置为false来将标志值设置为!editing state。

然后,您可以在该属性上添加选择器,并根据此属性显示或隐藏表单。

答案 4 :(得分:1)

好的。有可能请考虑以下示例来收听保存的联系人。

export class PageContactComponent implements OnInit, OnDestroy {

  destroy$ = new Subject<boolean>();
    
  constructor(private actionsListener$: ActionsSubject) {}

  ngOnInit() {
    this.actionsListener$
      .pipe(ofType(ContactActionTypes.SAVE_SUCCESS))
      .pipe(takeUntil(this.destroy$))
      .subscribe((data: any) => {
        // Do your stuff here
      });
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

在这里,我创建了一个名为ActionsSubject的{​​{1}}。在此示例中,我正在听actionsListener$(保存联系人时发生的操作)。在ContactActionTypes.SAVE_SUCCESS部分中描述您的代码,不要忘记破坏订阅。

编辑:操作如下所示:

subscribe

答案 5 :(得分:0)

Angular,Angular ...每次需要其他功能时都将包含另一个插件...:)

但是在给定的情况下,似乎没有效果就可以做到这一点。与@ kuncevic-dev

提到的方法相同
this.store.select(state => state.CompanyLicencesState).pipe(takeUntil(this.destroy)).subscribe((state: CompanyLicences.State) => {
  ...
});
this.store.dispatch(new GetCompanyLicences(filter)).pipe(finalize(() => (this.companyLicencsLoading = false)), takeUntil(this.destroy)).subscribe(() => {
  ...
});

会做这项工作。