Селектор нормализованного состояния ngrx - PullRequest
0 голосов
/ 15 декабря 2018

Я переписываю проект Ionic для работы с ngrx, потому что он сильно растет, и мне нужно поддерживать централизованное состояние.

Я реализовал его с помощью ngrx и использую нормализованные состояния с помощью Normalizr.

Теперь у меня есть сомнения относительно того, как передать немому компоненту заполненный объект:

Предположим, у меня есть два интерфейса:

interface Conversation {
    date: Date,
    lastMessage: string //this is the id of a message entity coming from normalizr
}

и

 interface Message {
       content: string
}

Теперь, когда я пытаюсь передать все разговоры немому компоненту, я использую селектор, подобный следующему:

getConversations() {

    //select all the conversations to have a shape of Conversation[]
    let conversations$ = this.store.select(state => Object.keys(state.entities.conversations).map( (id:string) => state.entities.conversations[id] ));

    //select all the messages in a shape { [id:string] : Message }
    let messages$ = this.store.select(state => state.entities.messages);

    return Observable.combineLatest(
      conversations$,
      messages$,
      (conversations, messages) => {
        return conversations.map(conversation => {
          return { ...conversation, lastMessage: messages[conversation.lastMessage] }

        });
      }
    )
  }

Но наблюдаемое, которое я возвращаю, не является массивомРазговор [], потому что

return { ...conversation, lastMessage: messages[conversation.lastMessage] }

помещает в lastMessage объект типа Message вместо String.

Я пытался использовать интерфейсы с типом объекта вместо строк

interface Conversation {
       date: Date,
       lastMessage: Message
    }

Но тогда я не могу использовать селектор, как

this.store.select(state => state.entities.messages[conversation.lastMessage]

, потому что он больше не является строкой.

Как мне этого добиться?

Спасибо

1 Ответ

0 голосов
/ 15 декабря 2018

Краткий ответ на этот вопрос будет следующим:

Вам необходимо выбрать свойство content из последнего сообщения, как в:

return { ...conversation, lastMessage: messages[conversation.lastMessage].content }

Более длинный ответ:

То же самое может быть достигнуто с помощью селекторов, преимущество в том, что он более повторно используется по сравнению с операторами RxJS.

Селектор - это чистая функция, которая принимает состояниев качестве аргумента и возвращает часть состояния магазина.Вместо того, чтобы просто возвращать данные, хранящиеся в хранилище, селектор может вычислять производные данные на основе доступных данных.Это позволяет хранить только основы, сохраняя дерево состояний максимально компактным.Другая важная часть заключается в том, что селекторы могут быть составлены, то есть селектор может принимать один или несколько других селекторов в качестве своего входа.

Например:

// getters
export const selectUser = (state: AppState) => state.selectedUser;
export const selectAllBooks = (state: AppState) => state.allBooks;

// create a selector with `createSelector` and use the getters above
export const selectVisibleBooks = createSelector(
  selectUser,
  selectAllBooks,
  (selectedUser: User, allBooks: Books[]) => {
    if (selectedUser && allBooks) {
      return allBooks.filter((book: Book) => book.userId === selectedUser.id);
    } else {
      return allBooks;
    }
  }
);

В вашем компонентечтобы выбрать выбранные книги, вы можете сделать:

this.books = this.store.pipe(select(selectVisibleBooks));

Дополнительная информация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...