尝试使用Redux的Reselect lib,如下所示:
// selectors.js
import { createSelector } from "reselect";
const loggedIn = state => {
return state.language.loggedIn;
};
export const loggedInSelector = createSelector(loggedIn);
用法如下:
import React from "react";
import { connect } from "react-redux";
import { Text, View } from "react-native";
import { loggedInSelector } from "./../lib/selectors/language";
const Foo = ({ loggedIn }) => {
return (
<View>
<Text>Foo - {loggedIn ? "logged in" : "not logged in"}</Text>
</View>
);
};
export default connect(state => {
console.log(state);
const loggedIn = loggedInSelector(state);
return {
loggedIn
};
})(Foo);
console.log(state)
的结果是:
language: {
loggedIn: false
}
但是,我收到一个类型错误:无法读取未定义的属性“语言”。在我看来,有人能看到我在哪里出现问题吗?我认为是Reselect相当简单的用例?
答案 0 :(得分:0)
结果是,我错过了createSelector
的第二个参数(似乎是必需的):
export const loggedInSelector = createSelector(loggedIn, l => l);
答案 1 :(得分:0)
正如您在自己的答案中指出的那样,您缺少转换功能。
const getLoggedIn = state => state.language.loggedIn
export const getloggedInMemoized = createSelector(loggedIn, i => i)
cannot read property 'language' of undefined
错误与您的reducer函数的初始状态有关。
在记住的选择器中,转换函数只是标识函数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
将确保仅在至少一个输入选择器的结果已更改的情况下才调用transform函数。
这是我认为微妙但关键的原因。 当返回
选择器的值是array
或object
。这非常
对性能很重要。 connect
的{{1}}功能
将对提供的道具执行简单的相等性检查,以查看是否
该组件需要重新渲染(添加时价格昂贵)。
例如。
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
的人将看到没有任何变化,并且确实
不需要重新渲染组件。