1、connect
connect用於連接React組件與 Redux store,其使用方法如下
connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
[mapStateToProps(state, [ownProps]): stateProps]是connect的第一個參數,其類型為function,允許我們將 store 中的數據作為 props 綁定到組件上。
const mapStateToProps = (store) => { return { count:store.count } }
(1)這個函數的第一個參數就是 Redux 的 store,我們不必將 store中的數據原封不動地傳入組件,可以根據 state 中的數據,動態地輸出組件需要的(最小)屬性。
(2)函數的第二個參數 ownProps,是組件自己的 props。有的時候,ownProps 也會對其產生影響。
當 state 變化,或者 ownProps 變化的時候,mapStateToProps 都會被調用,計算出一個新的 stateProps,(在與 ownProps merge 后)更新給組件。
[mapDispatchToProps(dispatch, ownProps): dispatchProps]將 action 作為 props 綁定到組件上,也會成為 MyComp 的 props。
stateProps 和 dispatchProps,都需要和 ownProps merge 之后才會被賦給組件。connect 的第三個參數就是用來做這件事。如果不傳這個參數,connect 就會使用 Object.assign替代該方法。
connect 的第四個參數[options] (Object) 如果指定這個參數,可以定制 connector 的行為,一般不用。
connect核心代碼:
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) { return function wrapWithConnect(WrappedComponent) { class Connect extends Component { constructor(props, context) { // 從祖先Component處獲得store this.store = props.store || context.store this.stateProps = computeStateProps(this.store, props) this.dispatchProps = computeDispatchProps(this.store, props) this.state = { storeState: null } // 對stateProps、dispatchProps、parentProps進行合並 this.updateState() } shouldComponentUpdate(nextProps, nextState) { // 進行判斷,當數據發生改變時,Component重新渲染 if (propsChanged || mapStateProducedChange || dispatchPropsChanged) { this.updateState(nextProps) return true } } componentDidMount() { // 改變Component的state this.store.subscribe(() = { this.setState({ storeState: this.store.getState() }) }) } render() { // 生成包裹組件Connect return ( <WrappedComponent {...this.nextState} /> ) } } Connect.contextTypes = { store: storeShape } return Connect; } }
可以看到connect是一個高階函數
首先,傳入mapStateToProps、mapDispatchToProps
然后,返回一個生產Component的函數(wrapWithConnect)
最后,將真正的Component作為參數傳入wrapWithConnect
這樣就生產出一個經過包裹的Connect組件,該組件具有如下特點:
通過props.store獲取祖先Component的storeprops包括stateProps、dispatchProps、parentProps,合並在一起得到nextState,作為props傳給真正的Component
componentDidMount時,添加事件this.store.subscribe(this.handleChange),實現頁面交互
shouldComponentUpdate時判斷是否有避免進行渲染,提升頁面性能,並得到nextState
componentWillUnmount時移除注冊的事件this.handleChange
2、Provider
Provider組件主要有以下兩個作用:
1、在原應用組件上包裹一層,使原來整個應用成為Provider的子組件
2、接收Redux的store作為props,通過context對象傳遞給子孫組件
其代碼如下
export default class Provider extends Component { getChildContext() { return { store: this.store } } constructor(props, context) { super(props, context) this.store = props.store } render() { return Children.only(this.props.children) } } if (process.env.NODE_ENV !== 'production') { Provider.prototype.componentWillReceiveProps = function (nextProps) { const { store } = this const { store: nextStore } = nextProps if (store !== nextStore) { warnAboutReceivingStore() } } } Provider.propTypes = { store: storeShape.isRequired, children: PropTypes.element.isRequired } Provider.childContextTypes = { store: storeShape.isRequired }
從上面的代碼可以看出Provider是通過context傳遞給子組件的,子組件通過connect獲得數據,實現過程如下,可以看到在沒有定義props的情況下,通過context直接取得store中的數據。
...
constructor(props, context) { this.store = props.store || context.store this.stateProps = computeStateProps(this.store, props) this.dispatchProps = computeDispatchProps(this.store, props) this.state = { storeState: null } this.updateState() } ...
轉自:https://www.jianshu.com/p/5726bb042bda