ngrx归一化状态选择器 [英] ngrx normalized state selector

查看:111
本文介绍了ngrx归一化状态选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重写一个与ngrx一起使用的Ionic项目,因为它正在增长,而且我需要保持集中状态.

I'm rewriting a Ionic project to work with ngrx because it is growing a lot and I need to maintain a centralized state.

我已经使用ngrx实现了它,并在Normalizr的帮助下使用归一化状态.

I have implemented it with ngrx and using normalized states with the help of Normalizr.

现在,我对如何将填充的对象传递给哑组件有疑问:

Now I have a doubt on how to pass to dumb component a populated object:

假设我有两个接口:

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

 interface Message {
       content: string
}

现在,当我试图将所有对话传递给愚蠢的组件时,我正在使用这样的选择器:

Now when I'm trying to get all conversations to pass to the dumb component I'm using a selector like this:

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] }

        });
      }
    )
  }

但是我要返回的Observable不是Conversation []数组,因为

But the Observable I'm returning is not an array of Conversation[] because

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

在'lastMessage'中放入了Message类型的对象,而不是String.

is putting inside 'lastMessage' an object of type Message instead of a String.

我尝试使用对象类型而不是字符串的接口

I tried to use interfaces with the object type instead of strings

interface Conversation {
       date: Date,
       lastMessage: Message
    }

但是我不能使用

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

因为它不再是字符串了.

because it is not a string anymore.

我该如何实现?

谢谢

推荐答案

此问题的简短答案如下:

The short answer to this question would be the following:

您需要从最后一条消息中选择content属性,如:

You need to select the content property from the last message, as in:

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

更长的答案:

使用选择器也可以实现相同的目的,其优点是与RxJS运算符相比,它更具可重用性.

The same can be achieved with selectors, this has the benefit that it's more re-usable in comparison with the RxJS operators.

选择器是一个纯函数,它将状态作为参数,并且 返回商店状态的一部分.而不是只返回 存储在商店中的数据,选择器可以根据以下内容计算派生数据 可用数据.这样您就可以只存储基础知识,保持 状态树尽可能紧凑.另一个重要的部分是 选择器可以组成,即:一个选择器可以采用一个或 多个其他选择器作为其输入.

A selector is a pure function that takes the state as an argument and returns a slice of the store’s state. Instead of just returning the data stored in the store, a selector can compute derived data based on the available data. This allows you to only store the basics, keeping the state tree as compact as possible. Another important part is that selectors could be composed, that is: a selector can take one or multiple other selectors as its input.

例如:

// 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;
    }
  }
);

在组件中选择要选择的书籍,您可以执行以下操作:

In your component to select select the books, you can do:

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

更多信息:

  • docs
  • Sharing data between modules is peanuts - A dive into NgRx selectors

这篇关于ngrx归一化状态选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆