所以,我正在使用redux和reselect工具createSelector
在mapStateToProps
中记住我的选择器,这很棒。
现在,我的商店中有一些标准化数据,以及需要来自商店的相互依赖数据的容器。
我现在正在这样做,并且它有效:
const getItemId = props => parseInt(props.match.params.itemId, 10)
const containerSelector = createSelector(getItemId, itemId =>
createSelector(
[getUser, getItem(itemId)],
(user, item) =>
createSelector(
[
getFoo(item.fooId),
getBar(item.barId)
],
(foo, bar) => ({ user, item, foo, bar })
)
)
)
const mapStateToProps = (state, ownProps) =>
containerSelector(ownProps)(state)(state)
export default connect(mapStateToProps)(Container)
问题:有更好的方法吗?
修改
感谢Tho Vu的回答,我可以简化并记忆,就像这样:
import { getUser, getItemById, getFooById } from 'selectors'
// Note: getStuffById are selector factories like:
// const getStuffById = id => state => state.stuff.objects[id]
const itemIdSelector = (_, props) => parseInt(props.match.params.itemId, 10)
const itemSelector = (state, props) => {
const itemId = itemIdSelector(state, props)
return getItemById(itemId)(state)
}
const fooSelector = (state, props) => {
const item = itemSelector(state, props)
return item ? getFooById(item.fooId)(state) : null
}
const mapStateToProps = createStructuredSelector({
user: getUser,
itemId: itemIdSelector,
item: itemSelector,
foo: fooSelector
})
但我仍然喜欢它吗?或者它已经好了吗?
答案 0 :(得分:1)
来自reselect
的文档:
当选择器连接到带连接的组件时, 组件道具作为第二个参数传递给选择器
因此,用于获取createSelector
的第一个itemId
图层实际上是不必要的,您可以将其替换为:
const getItem = (state, props) => {
const itemId = parseInt(props.match.params.itemId, 10)
return getItem(itemId)
}
其次,createSelector
具有以下属性:
使用createSelector创建的选择器的缓存大小为1.这 意味着它们总是在输入选择器的值时重新计算 更改,因为选择器只存储每个的前一个值 输入选择器。
这意味着您的自定义选择器会在user
,itemId
,item
,foo
,bar
的每次更改时重新计算。关于其他输入选择器很难说,但我没有看到user
和其他人之间的任何关系。因此,您应该仅为user
创建单独的选择器。
此外,createSelector
的目的是创建一个具有可保留memoization的选择器,因此以您的方式嵌套它们将导致每次外部重新计算时都会重新创建内部选择器。
我通常做的就是像这样压扁它们:
const getItem = (state, props) => {
const itemId = parseInt(props.match.params.itemId, 10)
return getItem(itemId)
}
const userSelector = createSelector(getUser, user => user)
const itemSelector = createSelector(getItem, item => item)
foo
和bar
更加困难,因为在您的代码中,选择器会查找item
,item.fooId
和foo
中的更改,但也会重新计算。我们仍然需要嵌套选择器,但需要分离foo
和bar
:
const fooFromItemSelector = createSelector(itemSelector, item => getFoo(item.fooId))
const fooSelector = createSelector(fooFromItemSelector, foo => foo)
同样适用于bar
。
最后,您需要将它们组合在一起以创建containerSelector
:
import { createStructuredSelector } from 'reselect'
const containerSelector = createStructuredSelector({
user: userSelector,
item: itemSelector,
foo: fooSelector,
bar: barSelector
})