首页 > 代码库 > 正式学习React(五) react-redux源码分析

正式学习React(五) react-redux源码分析

磨刀不误砍柴工,咱先把react-redux里的工具函数分析一下:

源码点这里

技术分享

 shallowEqual.js

 1 export default function shallowEqual(objA, objB) {
 2   if (objA === objB) {
 3     return true
 4   }
 5 
 6   const keysA = Object.keys(objA)
 7   const keysB = Object.keys(objB)
 8 
 9   if (keysA.length !== keysB.length) {
10     return false
11   }
12 
13   // Test for A‘s keys different from B.
14   const hasOwn = Object.prototype.hasOwnProperty
15   for (let i = 0; i < keysA.length; i++) {
16     if (!hasOwn.call(objB, keysA[i]) ||
17         objA[keysA[i]] !== objB[keysA[i]]) {
18       return false
19     }
20   }
21 
22   return true
23 }

这个几个api全都超级简单,我就不仔细讲解了,顾名思义,简单比较一下两个obj是否相等。 

storeShape.js

1 import { PropTypes } from ‘react‘
2 
3 export default PropTypes.shape({
4   subscribe: PropTypes.func.isRequired,
5   dispatch: PropTypes.func.isRequired,
6   getState: PropTypes.func.isRequired
7 })

顾名思义,强制性规定subscribe,dispacth,getState必须是func.

warning.js

 1 /**
 2  * Prints a warning in the console if it exists.
 3  *
 4  * @param {String} message The warning message.
 5  * @returns {void}
 6  */
 7 export default function warning(message) {
 8   /* eslint-disable no-console */
 9   if (typeof console !== ‘undefined‘ && typeof console.error === ‘function‘) {
10     console.error(message)
11   }
12   /* eslint-enable no-console */
13   try {
14     // This error was thrown as a convenience so that if you enable
15     // "break on all exceptions" in your console,
16     // it would pause the execution at this line.
17     throw new Error(message)
18     /* eslint-disable no-empty */
19   } catch (e) {}
20   /* eslint-enable no-empty */
21 }

就是用console.error 打印一下错误。

wrapActionCreators.js

1 import { bindActionCreators } from ‘redux‘
2 
3 export default function wrapActionCreators(actionCreators) {
4   return dispatch => bindActionCreators(actionCreators, dispatch)
5 }

上一篇讲过 bindActionCreators


它返回的这个对象直接是以 我们定义单个actionCreator为key的,actionCreator函数为value的包装,并在actionCreator里挂着了dispacth的函数。使用的时候,直接调用同名key函数,就直接分发action了,不需要

我们手动的 dispacth(actionCreator(内容)), 直接key(内容) 就行了。

 

------------------------------------------------------工具全部介绍完毕-----是不是so easy??!!!------------------------------

 现在主角登场:

技术分享

Provider.js

 

 1 import { Component, PropTypes, Children } from ‘react‘
 2 import storeShape from ‘../utils/storeShape‘
 3 import warning from ‘../utils/warning‘
 4 
 5 let didWarnAboutReceivingStore = false
 6 function warnAboutReceivingStore() {
 7   if (didWarnAboutReceivingStore) {
 8     return
 9   }
10   didWarnAboutReceivingStore = true
11 
12   warning(
13     ‘<Provider> does not support changing `store` on the fly. ‘ +
14     ‘It is most likely that you see this error because you updated to ‘ +
15     ‘Redux 2.x and React Redux 2.x which no longer hot reload reducers ‘ +
16     ‘automatically. See https://github.com/reactjs/react-redux/releases/‘ +
17     ‘tag/v2.0.0 for the migration instructions.‘
18   )
19 }
20 
21 export default class Provider extends Component {

//关键部分,将this.store加到了context里,这里,子组件就可以通过context直接拿到store,不需要一级一级props传递下去。
22 getChildContext() { 23 return { store: this.store } 24 } 25 26 constructor(props, context) { 27 super(props, context) 28 this.store = props.store 29 } 30 31 render() { 32 return Children.only(this.props.children) 33 } 34 } 35 36 if (process.env.NODE_ENV !== ‘production‘) { 37 Provider.prototype.componentWillReceiveProps = function (nextProps) { 38 const { store } = this 39 const { store: nextStore } = nextProps 40 41 if (store !== nextStore) { 42 warnAboutReceivingStore() 43 } 44 } 45 } 46 47 Provider.propTypes = {
//要求我们的 store对象里面的3个必须是func
48 store: storeShape.isRequired,

//要求我们形如这种格式的 <Provider store={store}> <App/> </Provider> ,<App>必须是react的element,其实它还要求了只能是放单element的,这也是render这个本身限定的!!可以看上面的Children.Only()
49 children: PropTypes.element.isRequired 50 }
// 这个是和getChildContext一样,必须加的。

//访问context 的属性是需要通过 contextTypes 指定可访问的 元素一样。getChildContext 指定的传递给子组件的属性需要先通过 childContextTypes 来指定,不然会产生错误。
51 Provider.childContextTypes = { 52 store: storeShape.isRequired 53 }

 

 关于context的用法,我在github上写了一个小demo。大家可以clone下来跑一跑,在我的代码基础上可以添加一下状态函数,看看react的状态生命周期的流程。点这里

 

对于上面的代码总结一下,Provider这个React 组件就是为了将Store挂在到Context中,然后我们写的APP 里就可以获得store了。

 

正式学习React(五) react-redux源码分析