NgRx 选择器和咖喱

NgRx selectors and currying

提问人:wonderful world 提问时间:7/4/2023 最后编辑:wonderful world 更新时间:7/10/2023 访问量:31

问:

我已经使用了一段时间,并试图理解用于创建选择器的功能语言功能或设计模式,如本 NgRx 文档页面上所述。来自面向对象编程的背景,看到许多函数而不是采用一堆属性的简单调用让我感到困惑。NgRx

使用什么函数式语言特征或设计模式来创建选择器?NgRx

JavaScript TypeScript 咖喱 ngrx 选择器

评论


答:

1赞 mat.hudak 7/6/2023 #1

我想最好的解释是,这个解决方案是为了强制执行一件事:单一事实来源

// Selects user and provides no option to somehow modify the state from which it takes the slice
export const selectUser = (state: AppState) => state.selectedUser;
// Same here
export const selectAllBooks = (state: AppState) => state.allBooks;
 
// Even combined selectors work only with current state. 
// Yes, there is some logic inside, but provide same inputs and you'll get same results.
export const selectVisibleBooks = createSelector(
  selectUser,
  selectAllBooks,
  (selectedUser: User, allBooks: Book[]) => {
    if (selectedUser && allBooks) {
      return allBooks.filter((book: Book) => book.userId === selectedUser.id);
    } else {
      return allBooks;
    }
  }
);

如果您有可能向选择器提供 a,或者在组合的情况下提供 a,您如何确定在选择之前没有修改它们?statepartial selectors

想象一下这样的情况:

//current state:
{
  user: {
    id: 1,
    name: 'John Doe'
  }
  books: [
    { id: 100, userId: 1, name: 'Exiting Vim - eventually' },
    { id: 200, userId: 2, name: 'Z-index: 10000000; - Real world CSS' }
  ]
}

// Component A

// Using selector like this, you are sure, that you'll get visible books
// for current user. In a predictable manner
this.result = this.store.select(selectVisibleBooks);

// Component B

// Now imagine you had the ability to provide user;
const user = this.store.select(selectUser);
this.result = this.store.select(selectVisibleBooks(user));

// What would stop you from doing this?
const oldUser = this.store.select(selectUser);
const user = { ...oldUser, id: 3 };
this.result = this.store.select(selectVisibleBooks(user));

// Component C
// Same thing, but imagine you provided your own version of state to the selector
const oldState = this.store.select(all); // Fake, imagine you're selecting everything
const state = { ...oldState, user: { id: 4, name: 'Jane Doe' }}
this.result = this.store.select(state, selectVisibleBooks);

// The "same selector" would return different things, depending on parameters, 
// breaking the 'Predictability' principle of the Redux/NgRx

正如我所说,我一直把它当作一种强制执行单一真相来源的形式。这是通过调整选择器来实现的,而不是让您在选择所需的状态切片时提供修改状态或切片的能力。

如果你想到带有道具的选择器——现在的工厂选择器,它们仍然只允许你发送一个参数来修改选择,但它们仍然依赖于 curried 函数,不允许你提供状态本身。