为什么使用reselect
在react-redux
的概念中,将组件分为容器组件与视图组件
-
容器组件
只负责逻辑计算,不负责视图呈现 -
视图组件
只负责视图部分,不负责逻辑计算
在react-redux
中的通过connect
将容器组件与视图组件连接起来。
connect(mapStateToProps, mapDispatchToProps)(View)
mapStateToProps
mapStateToProps是一个函数,函数返回一个需要通过props传递给视图组件的对象,
const mapStateToProps = (state, props) => {
// state一改变我就要取值
return {
todos: [1,2,3]
}
}
mapDispatchToProps
用来建立视图组件的参数到store.dispatch
方法的映射。它定义了哪些用户的操作应该当作Action
。
const mapDispatchToProps = (dispatch, ownProps) => {
return {
onClick: () => {
dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: ownProps.filter
});
}
};
}
在容器组件中,每次reducers
中的state
变更的时候(任何state包括其他模块的state),都会触发mapStateToProps
所在的函数,如果项目规模比较大,并且在mapStateToProps
中进行一些计算的时候,就会增加计算量,影响项目的运行效率。因此我们引入了reselect
。
如何使用reselect
reselect
可以对传入的依赖做一个缓存,如果传入的函数的结果不变,那返回的结果也不会变
reselect
使用方式
const mySelector = createSelector(
state => state.values.value1,
state => state.values.value2,
(value1, value2) => value1 + value2
)
// 也能把第一个参数作为一个数组
const totalSelector = createSelector(
[
state => state.values.value1,
state => state.values.value2
],
(value1, value2) => value1 + value2
)
举个例子
import { createSelector } from 'reselect'
const getPageA = state => {
// state一改变我就要取值
return state.pageB.get('number')
}
const getPageAObj = state => {
// state一改变我就要取值
return state.pageB.getIn(['obj'])
}
const selectorProps = createSelector([getPageA, getPageAObj], (number, nameObj) => {
// number与nameObj变更了后我才计算下面的,要是没变的话直接返回上次的值
return {
number:dealNumber(number)
}
})
export default connect(selectorProps, actionCreator)(View)
如上的例子,在state
变更的时候,就会触发getPageA
与getPageAObj
函数。如果createSelector
依赖的这两个函数的结果没有变更,那就不会执行dealNumber
相关的操作,而是直接返回上次已经计算好的结果。
总结:
-
在容器组件中采用
createSelector
对计算进行缓存 -
在依赖函数中只直接取值,不针对值进行计算,将计算放到
createSelector
中最后一个参数的函数中。 -
createSelector
中的依赖结果值要唯一,如果采用了Immutable
结构,不能在依赖函数中执行toJS()
方法。因为toJS()
每次都返回一个新的对象,createSelector
内部采用===
做简单比较 -
如果采用了
Immutable
对数据进行了包装,那state
中某个属性变更后返回的都是一个新的state
, 这样在createSelector
中的依赖函数所返回的值都将是一个新的值,也将会触发相关的重新计算。如果计算量比较大的话,可以考虑将state
拆分成多个子state
, 再通过combineReducers
组合起来。否则createSelector
也就不起作用了。
!> 注意:关于state
变更。如果有pageA
与pageB
,通过redux
的combineReducers
方法将pageA
与pageB
合并成一个大的state
,更改了pageA
中的state的时候,也会触发pageB
中所绑定的函数
网友评论