2

我的问题是这个关于 redux 存储中分页数据形状的优秀问答的延续。我在 Angular 2 应用程序中使用 ngrx/store。

{
  entities: {
    users: {
      1: { id: 1, name: 'Dan' },
      42: { id: 42, name: 'Mary' }
    }
  },
  visibleUsers: {
    ids: [1, 42],
    isFetching: false,
    offset: 0
  }
}

基于上述形状,我相信如果来自传入请求有效负载的偏移量(或页面、排序等)发生变化,那么可见用户以及通过调用数据库的用户实体都会发生变化。我有一些动作和减速器功能来处理这个问题,它按预期工作。如果偏移量保持不变并且用户以离开页面的方式返回页面,则用户实体应该由商店而不是数据库返回。

我苦苦挣扎的地方是该逻辑的放置位置以及使用哪些 rxjs 运算符(仍在学习这一点)。

认为正确的地方是一种效果。这是我现在在我的 angular2 应用程序中拥有的内容(我正在注入 Actions、Store 和我的 UserService),每次加载页面时都会提取新数据。

@Effect loadUsers$ = this.actions$
     .ofType('LOAD_USERS')
     .switchMap(() => this.userService.query()
         .map((results) => {
             return new LoadUsersSuccessAction(results);
         }))
     .catch(() => Observable.of(new LoadUsersFailureAction()));

我最好的主意是这样的:

@Effect loadUsers$ = this.actions$
     .ofType('LOAD_USERS')
     .withLatestFrom(this.store.select(state => state.visibleUsers.offset))
     .switchMap(([action, state]) => {
         //something that looks like this??
         //this syntax is wrong and I can't figure out how to access the action payload
         state.offset === payload.offset 
            ? this.store.select(state => state.entities.users) 
            : this.userService.query()
         }
         .map((results) => {
             return new LoadUsersSuccessAction(results);
         }))
     .catch(() => Observable.of(new LoadUsersFailureAction()));

不知道如何使这项工作。提前谢谢。

4

1 回答 1

5

我不喜欢回答自己的问题,但我花了很长时间才找到答案。我不会接受这个答案,因为我不确定这是处理事情的最佳方式(仍在学习细节)。但是,它确实可以完美运行。

我在 github gist中找到了正确的语法。此代码与我的示例不匹配,但它通过使用某种条件返回商店或可观察的 api 清楚地演示了“条件 ngrx 效果的 2 个选项”。

希望这可以帮助某人。

这里是:

  @Effect()
  selectAndLoadStore$: Observable<Action> = this.actions$
    .ofType(storeActions.SELECT_AND_LOAD_STORE)
    .withLatestFrom(this.store.select(ngrx.storeState))
    .map(([action, storeState]) => [action.payload, storeState])
    .switchMap(([storeName, storeState]) => {
      const existsInStore = Boolean(storeState.urlNameMap[storeName]);
      return Observable.if(
        () => existsInStore,
        Observable.of(new storeActions.SetSelectedStore(storeName)),
        this.storeService.getByUrlName(storeName)
          .map(store => new storeActions.LoadSelectedStoreSuccess(store))
      );
    });

  @Effect()
  selectAndLoadStore$: Observable<Action> = this.actions$
    .ofType(storeActions.SELECT_AND_LOAD_STORE)
    .withLatestFrom(this.store.select(ngrx.storeState))
    .map(([action, storeState]) => [action.payload, storeState])
    .switchMap(([storeName, storeState]) => {
      const existsInStore = Boolean(storeState.urlNameMap[storeName]);
      let obs;
      if (existsInStore) {
        obs = Observable.of(new storeActions.SetSelectedStore(storeName));
      } else {
        obs = this.storeService.getByUrlName(storeName)
          .map(store => new storeActions.LoadSelectedStoreSuccess(store));
      }
      return obs;
    });
于 2017-04-07T21:47:34.080 回答