createStructuredSelector中选择器使用逻辑OR运算符失效如何解决
问题原因
你之前的写法pending: selectIsPending_1 || selectIsPending_2存在本质错误:||运算符是在选择器初始化定义阶段执行的,不是在每次传入state计算结果阶段执行的。JavaScript中函数本身是真值,因此这段表达式永远只会返回第一个选择器selectIsPending_1,selectIsPending_2从始至终都没有被传入选择器集合,自然永远不会执行,最终pending值只会取selectIsPending_1的返回结果,初始加载后就恒为false。
你目前用的临时方案pending: () => selectIsPending_1(state) || selectIsPending_2(state)虽然能跑通逻辑,但存在两个明显问题:
- 无参箭头函数依赖闭包捕获外层的
state变量,写法不符合reselect选择器的入参规范,容易出现作用域异常 - 这个匿名函数没有经过reselect记忆化包装,每次state更新都会重复执行计算,完全失去了reselect的性能优化能力
正确写法
推荐使用reselect官方提供的createSelector方法,先将OR逻辑封装为带记忆化能力的独立选择器,再传入createStructuredSelector:
// 组合两个pending状态的判断逻辑,生成带缓存的新选择器 const selectCombinedPending = createSelector( [selectIsPending_1, selectIsPending_2], (isPending1, isPending2) => isPending1 || isPending2 ) const mapStateToProps = state => ({ someProp: state.someProp, ...createStructuredSelector({ pending: selectCombinedPending })(state) })
这种写法下,只有当selectIsPending_1或selectIsPending_2的返回值发生变化时,才会重新执行OR逻辑计算pending的值,既保证逻辑正确,也保留了reselect的记忆化性能优势。
如果只是临时快速实现,不想额外拆分选择器,也可以直接给createStructuredSelector传入符合签名的选择器函数(入参为state),但这种写法没有缓存效果,不推荐在生产环境使用:
const mapStateToProps = state => ({ someProp: state.someProp, ...createStructuredSelector({ pending: (state) => selectIsPending_1(state) || selectIsPending_2(state) })(state) })
注意事项
- 所有涉及选择器返回值的逻辑运算,都要放在
createSelector的结果计算函数内执行,不要直接在选择器定义层对选择器函数本身做逻辑运算 createStructuredSelector接收的对象属性值必须是符合(state, ownProps?) => 任意值签名的选择器函数,不要传入依赖闭包捕获变量的无参函数
内容的提问来源于stack exchange,提问作者Anton Karpenko
相关产品推荐
相关产品推荐

