- 首先react-redux在使用connect的时候,会将整个store挂在当前这个HOC的实例上,然后取出state,并将state挂在当前这个HOC的state上,代码如下:
class Connect extends Component {
......
constructor(props, context) {
super(props, context)
this.version = version
this.store = props.store || context.store
invariant(this.store,
`Could not find "store" in either the context or ` +
`props of "${this.constructor.displayName}". ` +
`Either wrap the root component in a <Provider>, ` +
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
)
const storeState = this.store.getState()
this.state = { storeState }
this.clearCache()
}
.......
}
- 之后会在componentDidMount 中做 Subscribe 代码如下
componentDidMount() {
this.trySubscribe()
}
trySubscribe() {
if (shouldSubscribe && !this.unsubscribe) {
this.unsubscribe = this.store.subscribe(::this.handleChange)
this.handleChange()
}
}
- Subscribe 方法,会将所有的回调注册到一个队列里面,代码如下
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
- 发起dispatch后,redux会同步调用所有注册的回调函数,代码如下
function dispatch(action) {
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
const listeners = currentListeners = nextListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
- 回调函数则触发setState,并更新HOC中的store的值副本,并比较两次的store的值,来确定store是否更改
handleChange() {
if (!this.unsubscribe) {
return
}
const prevStoreState = this.state.storeState
const storeState = this.store.getState()
if (!pure || prevStoreState !== storeState) {
this.hasStoreStateChanged = true
this.setState({ storeState })
}
}
- 从代码上来看,redux 依靠 shouldComponentUpdate 来判断是否需要执行render
shouldComponentUpdate() {
return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged
}
- 通过 componentWillReceiveProps 中对Props进行浅比较,来判断props是否更改
componentWillReceiveProps(nextProps) {
if (!pure || !shallowEqual(nextProps, this.props)) {
this.haveOwnPropsChanged = true
}
}
- 那么从代码来看的话,只要发起了dispatch 就会产生新的sotre,会引发rerender