Как вы указали в своем собственном ответе, вам не хватает функции преобразования.
cannot read property 'language' of undefined
cannot read property 'language' of undefinedОшибка будет относиться к исходному состоянию вашей функции редуктора.
В вашем memoized селекторе функция преобразования - это только функция идентификации, i => iкоторая является очень сильным индикатором того, что селектор, который вы передали ( const loggedIn = state => state.language.loggedIn), не нуждался в замещении. Зачем? Из-за connectтого, react-reduxчто внутренне сделайте свою собственную проверку равенства, чтобы убедиться, что компонент только повторно отображается, если изменяется один или несколько реквизитов.
В принципе, ваш первоначальный loggedInселектор отлично работает, и нет необходимости в дополнительных накладных расходах createSelector(хотя и малых).
Когда использовать createSelector?
-
Каждый раз, когда вы комбинируете результат двух или более селекторов , поскольку синтаксис createSelectorдействительно подходит для создания этих селекторов. например.
const taxSelector = createSelector(
subtotalSelector,
taxPercentSelector,
(subtotal, taxPercent) => subtotal * (taxPercent / 100)
)
-
Каждый раз, когда селектор делает что-то дорогостоящее . createSelectorбудет гарантировать, что функция преобразования вызывается только в том случае, если результат по меньшей мере одного из селекторов ввода изменился.
-
И это тонкая, но ключевая причина, на мой взгляд. Когда возвращаемое значение селектора является a arrayилиobject . Это очень важно для производительности. connectФункция react-redux будет выполнять простую проверку равенства реквизита , предоставляемых увидеть , если необходимо повторно вынесено (дорого , когда он складывает) компонент. например.
const getSaleItems = state => {
const items = getShopItems(state)
return items.filter(i => i.isOnSale)
}
Каждый раз, когда он getSaleItemsвызывается, он возвращает новый массив. Даже если возвращаемый массив getShopItemsне изменился. Это означает, что react-reduxбудет повторно отображать компонент, потому что, когда он выполняет проверку неглубокого равенства на реквизитах, при условии, что он увидит, что массив изменился.
С другой стороны, при использовании createSelector:
const getSaleItems = createSelector(
getShopItems,
items => items.filter(i => i.isOnSale)
}
Если результат getShopItemsне изменился, последовательные вызовы getSaleItemsвернут один и тот же экземпляр массива, потому что результат будет сохранен в памяти. Это означает, что неглубокая проверка равенства react-reduxувидит, что ничего не изменилось и что ему не нужно повторно отображать компонент ??.