下篇conncect
找了很多react-redux的源码博客去学习,但无奈reacy-redux更新贼快,到目前为止我没有找到一个是我现在看到的源码版本的博客讲解,无奈现在这次和之前博客是完全不一样,使用了react中的HOOK来实现,我枯了,useMemo, useEffect。。。
Provider
:配合 connect 来达到跨层级传递数据
使用时只需将Provider定义为整个项目最外层的组件,并设置好store。
底层实现使用了context,下面是源码部分。(只摘录了重点部分),内部还结合了观察者模式,比如store改变后会执行所有的Listener
function Provider({ store, context, children }) {
const contextValue = useMemo(() => {
const subscription = new Subscription(store)
subscription.onStateChange = subscription.notifyNestedSubs
return {
store,
subscription
}
}, [store])
const previousState = useMemo(() => store.getState(), [store])
useEffect(() => {
const { subscription } = contextValue
subscription.trySubscribe()
if (previousState !== store.getState()) {
subscription.notifyNestedSubs()
}
return () => {
subscription.tryUnsubscribe()
subscription.onStateChange = null
}
}, [contextValue, previousState])
//context:是可以自定义的context,如果不传即用内部创建的context
const Context = context || ReactReduxContext
return <Context.Provider value={contextValue}>{children}</Context.Provider>
}
解析:
- useMemo:把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。(作用:性能优化)
- useEffect:组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。要实现这一点,useEffect 函数需返回一个清除函数。第二个参数是依赖项,和useMemo的第二个参数一样,只有依赖项改变了才会重新创建。
- children:children就是传给Context.Provider的children
- Subscription:Subscription对象的作用是监听store的变化并执行对应的listeners
// 初始化的功能
trySubscribe() {
if (!this.unsubscribe) {
this.unsubscribe = this.parentSub
? this.parentSub.addNestedSub(this.handleChangeWrapper)
: this.store.subscribe(this.handleChangeWrapper) // 给store上面添加了一个观察者,当store改变会执行所有listeners
this.listeners = createListenerCollection()
}
}