ngrx / store эффекты вложенных объектов

Я изучаю Angular 2, и я пытаюсь использовать ngrx / store, но у меня есть некоторые трудности с некоторыми особыми случаями.

Пример. Я пытаюсь удалить родительский объект. Я хочу удалить также дочерние объекты.

Вот мои сущности:

export class Discussion {
  id: string;
  name: string;
  createdAt: Date;
  posts: Post[];
}

export class Post {
  id: string;
  title: string;
  data: string;
  createdAt: Date;
  comments: Comment[];
}

export class Comment {
  id: string;
  data: string;
  createdAt: Date;
}

Я использую normalizr, чтобы сгладить свое состояние, чтобы мое сохраненное обсуждение выглядело так:

{
  id: "1",
  name: "First dicussion",
  createdAt: "...",
  posts: ["1", "2", "3", "5"]
}

У меня есть 3 редуктора, один редуктор для обсуждений, еще один для сообщений и последний для комментариев. Все редукторы обрабатывают действие удаления своего собственного типа. Вот пример редуктора обсуждения:

export function reducer(state = initialState, action: discussion.Actions): State {
switch (action.type) {
    case discussion.REMOVE: {
        const idToRemove = action.payload;
        const newEntities = state.entities;
        delete newEntities[idToRemove];
        return Object.assign({}, state, {
            entities: newEntities
        });
    }
}}

Мои действия выглядят так:

export class RemoveAction implements Action {
readonly type = REMOVE;

/**
 * Constructor
 * @param payload The id of the discussion to remove
 */
constructor(public payload: string) { }
}

Когда я удаляю обсуждение, я хочу удалить сообщения, связанные с обсуждением, и эффект сообщений удалит комментарии, связанные с удаленными сообщениями. Я использовал эффекты ngrx do this, поэтому я использовал этот эффект:

@Effect()
removeDiscussion: Observable<Action> = this._actions
.ofType(dicussion.REMOVE)
.map((action: discussion.RemoveAction) => action.payload)
.mergeMap(discId => {

    // How to get posts from discussion id ???

    // Fire related Actions
    return [
        new posts.RemoveAction(postsToRemove)
    ];
});

Мой вопрос в том, как удалить сообщения из идентификатора обсуждения?

Спасибо за прочтение.


person Lopeur    schedule 30.05.2017    source источник


Ответы (1)


Вы можете получить доступ к магазину в эффекте, используя withLatestFrom.
(import 'rxjs/add/operator/withLatestFrom';)

Добавьте магазин в класс эффектов:

constructor(private _actions: Actions, private store: Store<fromRoot.State>)

Используйте его в эффекте:

@Effect()
removeDiscussion: Observable<Action> = this._actions
    .ofType(dicussion.REMOVE)
    .map((action: discussion.RemoveAction) => action.payload)
    .withLatestFrom(this.store, (payload, state) => ({ discId: payload, state }))
    .mergeMap(({ discId, state }) => {
        // access the posts array of the discussion
        const postsToRemove = state.discussions[discId].posts;

        // Fire related Actions
        return [
            new posts.RemoveAction(postsToRemove)
        ];
    });

Синтаксис .mergeMap(({ discId, state }) => ... называется деструктуризацией.
Если вам не нравится этот синтаксис, его можно заменить на .mergeMap((payloadAndState) => .... Тогда вы получите доступ к discId, выполнив payloadAndState.discId

person mtx    schedule 03.06.2017
comment
Привет mtx, Спасибо за ответ. Это то, что я искал. Я не знал withLatestFrom, поэтому мне было интересно, как получить доступ к объекту состояния. Кроме того, синтаксис деструктуризации довольно крутой, спасибо и за это. Для людей, у которых есть ошибка при использовании withLatestFrom, не забудьте добавить import 'rxjs/add/operator/withLatestFrom';. Так как я новичок, забыл добавить. - person Lopeur; 06.06.2017
comment
Рад, что смог помочь. Я добавил оператор импорта к ответу на случай, если кто-то еще наткнется на этот вопрос. Спасибо за подсказку! - person mtx; 06.06.2017