Стандартный селектор повторного выбора аннулирует его мемоизированное значение и пересчитывает его, если селекторы ввода не проходят строгую проверку равенства:
export const selectEmailsFromComments = createSelector(
selectComments, // returns an array of comments
comments => commentsToEmails(comments)
)
Поскольку комментарии являются массивом, а не примитивным значением, редукторы redux обычно создать новый фрагмент состояния, чтобы избежать побочных эффектов, похоже, что приведенное выше никогда не мемоизируется, потому что массив комментариев, возвращаемый selectComments
, всегда будет иметь другую ссылку.
Чтобы решить эту проблему, можно создать Создатель настраиваемого селектора , например, для введения мелких проверок равенства:
const createShallowEqualSelector = createSelectorCreator(
defaultMemoize,
shallowEqual
)
export const selectEmailsFromComments = createShallowEqualSelector(
selectComments, // returns an array of comments
comments => commentsToEmails(comments)
)
Это работает, если комментарии действительно являются простыми объектами, и мы хотим пересчитывать электронные письма всякий раз, когда изменяется какой-либо из свойств комментариев.
Но что, если мы хотим только пересчитать электронные письма, если, например, количество комментариев изменилось? Как мы могли бы реализовать пользовательскую проверку равенства? Я ожидаю, что сработает следующее:
type ComparisonFunction<B extends object = {}> = (prev: B, next: B, index: number) => boolean
const createCustomEqualSelector = <B extends object = {}>(
equalFn: ComparisonFunction<B>
) => createSelectorCreator<ComparisonFunction<B>>(defaultMemoize, equalFn)
const commentsEqualFn = (a: IComment[], b: IComment[], index: number) =>
a.length === b.length
export const selectEmailsFromComments = createCustomEqualSelector(
commentsEqualFn
)(
selectComments, // returns an array of comments
comments => commentsToEmails(comments)
)
Однако это возвращает следующую ошибку Typescript для defaultMemoize:
(alias) function defaultMemoize<F extends Function>(func: F, equalityCheck?: (<T>(a: T, b: T, index: number) => boolean) | undefined): F
import defaultMemoize
Argument of type '<F extends Function>(func: F, equalityCheck?: (<T>(a: T, b: T, index: number) => boolean) | undefined) => F' is not assignable to parameter of type '<F extends Function>(func: F, option1: ComparisonFunction<B>) => F'.
Types of parameters 'equalityCheck' and 'option1' are incompatible.
Type 'ComparisonFunction<B>' is not assignable to type '<T>(a: T, b: T, index: number) => boolean'.
Types of parameters 'prev' and 'a' are incompatible.
Type 'T' is not assignable to type 'B'.ts(2345)
Как мне разрешить эту ошибку типа для настраиваемой функции равенства повторного выбора createSelector ?