注:这篇文章只是解说React Redux这一层,并不包括Redux部份。Redux有设计去进修,等今后进修了Redux源码今后再做剖析
注:代码基于如今(2016.12.29)React Redux的最新版本(5.0.1)
Connect东西类篇(2)
verifySubselectors.js
这里有四个参数:
mapStateToProps, mapDispatchToProps, mergeProps都是经由mapDispatchToProps, mapStateToProps, mergeProps封装过的
displayName是option内里传入的
重要做的是搜检传入的mapStateToProps,mapDispatchToProps,mergeProps是不是存在,由于这里的对象是经由几个map要领封装过的,所以不存在就申明开辟传入的值是毛病的。同时搜检是不是有dependsOnOwnProps这个属性,假如没有给一个warning.
import warning from '../utils/warning'
function verify(selector, methodName, displayName) {
if (!selector) {
throw new Error(`Unexpected value for ${methodName} in ${displayName}.`)
} else if (methodName === 'mapStateToProps' || methodName === 'mapDispatchToProps') { //只搜检mapStateToProps和mapDispatchToProps, 由于mergeProps要领不须要
if (!selector.hasOwnProperty('dependsOnOwnProps')) {
warning(
`The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.`
)
}
}
}
export default function verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, displayName) {
verify(mapStateToProps, 'mapStateToProps', displayName)
verify(mapDispatchToProps, 'mapDispatchToProps', displayName)
verify(mergeProps, 'mergeProps', displayName)
}
selectorFactory.js
这里重要担任猎取处置惩罚过的mapStateToProps, mapDispatchToProps, mergeProps和传入的options,来举行props的兼并,末了返回兼并后的效果。个中,当pure为true的时刻,会对props举行存储,便于下一次比较,假如经由过程比较两个雷同,那末就不转变props对象,削减不必要的re-render。
在connectAdvanced.js内里看到这么一段解释:
selectoryFactory要领返回的是一个function,这个function的作用是依据Redux Store state, props和dispatch盘算新的props. 在connectAdvanced中会供应dispatch给selectorFactory,以便selectorFactory能够对actionCreator举行绑定。connectAdvanced猎取的option设置会直接被传给selectorFactory,个中就包括了displayName和wrappedComponent(实在另有一些对照的要领在内里)。
selectorFactory担任纪录一切的状况(props, store state, dispatch, mergedProps),以便在部份状况发作转变,而不影响组件衬着的时刻,能够防止不必要的衬着。
finalPropsSelectorFactory
export default function finalPropsSelectorFactory(dispatch, {
initMapStateToProps,
initMapDispatchToProps,
initMergeProps,
...options
}) {
const mapStateToProps = initMapStateToProps(dispatch, options)
const mapDispatchToProps = initMapDispatchToProps(dispatch, options)
const mergeProps = initMergeProps(dispatch, options)
if (process.env.NODE_ENV !== 'production') {
verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, options.displayName)
}
const selectorFactory = options.pure
? pureFinalPropsSelectorFactory
: impureFinalPropsSelectorFactory
return selectorFactory(
mapStateToProps,
mapDispatchToProps,
mergeProps,
dispatch,
options
)
}
这里只是给mapStateToProps, mapDispatchToProps, mergeProps传入dispatch和options对象,然后依据pure的值传给差异的要领举行处置惩罚。
假如pure是true, 那末selectorFactory返回的selector会担任存储末了效果。假如效果没有发作转变,那末connectAdvanced的shouldComponentUpdate就会返回false。
假如pure是false, 那末selector永久会返回一个新的对象,同时shouldComponentUpdate永久都返回true
这个factory要领会返回一个function,吸收Redux Store和ownProps作为参数。作用是,每次store或ownProps发作转变今后,挪用这个返回的function,猎取更新后的终究props。
impureFinalPropsSelectorFactory
export function impureFinalPropsSelectorFactory(
mapStateToProps,
mapDispatchToProps,
mergeProps,
dispatch
) {
return function impureFinalPropsSelector(state, ownProps) {
return mergeProps(
mapStateToProps(state, ownProps),
mapDispatchToProps(dispatch, ownProps),
ownProps
)
}
}
依据pure即是false的状况,这里会永久返回一个新的对象。存粹的、不加任何推断的挪用mergeProps对几个props的构造举行兼并。
这里返回的值的花样是:(state, ownProps)=>final props
。
pureFinalPropsSelectorFactory
export function pureFinalPropsSelectorFactory(
mapStateToProps,
mapDispatchToProps,
mergeProps,
dispatch,
{ areStatesEqual, areOwnPropsEqual, areStatePropsEqual }
) {
let hasRunAtLeastOnce = false // 是不是是第一次挪用,第一次挪用不须要做是不是转变的搜检
let state // 影象上一次的state
let ownProps // 影象上一次的ownProps
let stateProps // 影象mapStateToProps返回的props
let dispatchProps // 影象mapDispatchToProps返回的props
let mergedProps // 影象末了兼并后的效果
// 第一次挪用的时刻,地道记着一切的效果
function handleFirstCall(firstState, firstOwnProps) {
state = firstState
ownProps = firstOwnProps
stateProps = mapStateToProps(state, ownProps)
dispatchProps = mapDispatchToProps(dispatch, ownProps)
mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
hasRunAtLeastOnce = true
return mergedProps
}
// 当两个都发作转变。。。
function handleNewPropsAndNewState() {
stateProps = mapStateToProps(state, ownProps) // ownProps发作了转变,一定须要挪用猎取新的props
if (mapDispatchToProps.dependsOnOwnProps)
dispatchProps = mapDispatchToProps(dispatch, ownProps)
mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
return mergedProps
}
// 假如只要父组件传入的props发作了转变,那末须要依据dependsOnOwnProps来举行更新
function handleNewProps() {
if (mapStateToProps.dependsOnOwnProps)
stateProps = mapStateToProps(state, ownProps)
if (mapDispatchToProps.dependsOnOwnProps)
dispatchProps = mapDispatchToProps(dispatch, ownProps)
// 由于ownProps发作了转变,所以不须要举行搜检,直接挪用mergeProps要领
mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
return mergedProps
}
// 假如只要Redux store state发作了转变,那末只用更新mapStateToProps的返回值,由于dispatchProps和Redux State无关
function handleNewState() {
const nextStateProps = mapStateToProps(state, ownProps)
const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps)
stateProps = nextStateProps
if (statePropsChanged)
mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
return mergedProps
}
// 除第一次挪用外,每次都须要对种种效果举行搜检,然后纪录必要的效果
function handleSubsequentCalls(nextState, nextOwnProps) {
const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps) // 搜检ownProps是不是发作转变
const stateChanged = !areStatesEqual(nextState, state) // 搜检Redux store state是不是发作转变
state = nextState
ownProps = nextOwnProps
// 依据转变的差异,挪用差异的要领。削减不必要的运算
if (propsChanged && stateChanged) return handleNewPropsAndNewState()
if (propsChanged) return handleNewProps()
if (stateChanged) return handleNewState()
return mergedProps
}
return function pureFinalPropsSelector(nextState, nextOwnProps) {
return hasRunAtLeastOnce
? handleSubsequentCalls(nextState, nextOwnProps)
: handleFirstCall(nextState, nextOwnProps)
}
}
当pure即是true的时刻,须要做出种种搜检来剖断是不是须要挪用要领,来猎取新的props.
当Redux state发作转变,ownProps没变的时刻
1) 由于mapDispatchToProps并没有基于Redux State,所以dispatchProps是须要举行更新的。2) 而mapStateToProps是基于Redux State的,所以须要挪用mapStateToProps要领也许”新的”stateProps。由于State发作转变,并不一定会形成返回效果的转变,所以须要依据搜检后的效果来剖断是不是挪用mergeProps要领。当OwnProps发作转变,Redux State没有转变的时刻
1) 由于mapDispatchToProps和mapStateToProps都能够基于ownProps,所以须要依据dependsOnOwnProps属性来搜检,推断是不是须要挪用要领举行更新。2) ownProps作为mergeProps的一个必要参数,所以不须要做任何推断,mergePorps必需被挪用当Redux Store, OwnProps都发作了转变
综合之前的两点,mapStateToProps必需挪用,mapDispatchToProps依据dependsOnOwnProps属性挪用,mergeProps必需挪用
一点总结:
在connect定义的时刻,平常只管运用pure:true的状况(默认值),由于在这类状况下,会对props举行差异搜检。假如没有转变,就不会去挪用connectAdvanced组件去更新。假如内部组件同时依据 除 父组件传入的props和Redux store的其他状况举行更新衬着,那末pure必需是false。
option中的areStatesEqual(默认值为===),areOwnPropsEqual(默认值为shallowEqual), areStatePropsEqual(默认值为shallowEqual), areMergedPropsEqual(默认值为shallowEqual),能够依据须要来修正这几个参数,当pure为true的时刻,搜检更多不必要的re-render