對React-redux中connect方法的理解

關於React-redux

Redux是React全家桶的重要一員,以前在知乎上也看到相似的提問:該如何通俗易懂的理解Redux?
Redux是JavaScript的狀態容器,Redux的概念簡單明瞭: javascript

1. 應用中全部的狀態都是以一個對象樹的形式存儲在一個單一的store中;
2. 當你想要改變應用的中的狀態時,你就要dispatch一個action,這也是惟一的改變state的方法;
3. 經過編寫reducer來維護狀態,返回新的state,不直接修改原來數據;java

爲何會有Redux

在React中,數據的傳遞主要採用state和props,props得由父級分發下來,而state是組件中可自行管理的狀態,這意味着React並無讓數據回溯的能力,數據只能單向向下分發,或者自行內部處理,舉一個簡單的例子,父組件可使用props向子組件傳遞數據,子組件能夠經過觸發回調函數來改變父組件的狀態,若是是那種沒有嵌套關係的組件,該如何來實現通訊呢?爲了解決這個問題,Redux的方法就是將store放在根目錄頂層組件中,一層層往下分發給各子組件,在子組件中進行調用,Redux的做用是讓狀態變得更加可預測、而且更容易管理。react

Redux由Flux框架演變而來,但在Flux的基礎上Redux改變了整個框架中某些角色的做用,例如在Flux中你能夠擁有多個store,每一個store存儲本身對應的那部分狀態,在Redux中,你只能維護一個store,存儲了整個應用的全部狀態,Redux更傾向於把store分發下去,dispatch action的時候,reducer根據狀態對象的key值再將store進行拆分,reducer能拿到store中對應的那一部分進行處理,Redux提供createStore、combineReducers、applyMiddleware等一系列方法來配合React-redux使用幫咱們更好的對這個store進行管理,這裏要詳講的是React-redux中的connect方法。git

Store與視圖層的綁定

Provider組件

想要把store綁定在視圖層上,得用到React-redux中的兩個主角:Provider和Connect,在api文檔第一段話,做者說一般狀況下你沒法使用connect()去connect一個沒有繼承Provider的組件,也就是說若是你想在某個子組件中使用Redux維護的store數據,它必須是包裹在Provider中而且被connect過的組件,Provider的做用相似於提供一個大容器,將組件和Redux進行關聯,在這個基礎上,connect再進行store的傳遞。github

Provider組件源碼:redux

export function createProvider(storeKey = 'store', subKey) {
......
class Provider extends Component {
    getChildContext() {
        return { [storeKey]: this[storeKey], [subscriptionKey]: null }
    }
    constructor(props, context) {
        super(props, context)
        this[storeKey] = props.store;
    }

    render() {
        return Children.only(this.props.children)
    }
}
}

從源碼中能夠看到,做者用了React的Context,Context解決了一個React中很常見的問題:當你的組件嵌套愈來愈深的時候,context能讓你父組件和其它裏層組件之間的通訊變的更方便,createProvider方法將返回一個Provider組件,該組件接受store和子組件,在Provider中定義了getChildContext方法來傳遞store,那麼在子組件中利用contextTypes,你就能利用context訪問到父級組件傳遞的store數據了。api

<Provider store>app

Props框架

  1. store:應用中惟一的狀態storeide

  2. children: 應用的子組件

例子:

<Provider store={store}>
    <Router history={history}>
    <Route path="/" component={App}>
        <Route path="foo" component={Foo}/>
        <Route path="bar" component={Bar}/>
    </Route>
    </Router>
</Provider>

connect方法

來看下connect函數究竟是如何將store和組件聯繫在一塊兒的,注意到api文檔中有這樣的一句話:

It does not modify the component class passed to it; instead, it returns a new, connected component class for you to use.

connenct並不會改變它「鏈接」的組件,而是提供一個通過包裹的connect組件。 conenct接受4個參數,分別是mapStateToProps,mapDispatchToProps,mergeProps,options(使用時注意參數位置順序)。

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

mapStateToProps(state, ownProps) 方法容許咱們將store中的數據做爲props綁定到組件中,只要store更新了就會調用mapStateToProps方法,mapStateToProps返回的結果必須是object對象,該對象中的值將會更新到組件中,例子:

const mapStateToProps = (state) => {
    return ({
        count: state.counter.count
    })
}

mapDispatchToProps(dispatch, [ownProps]) 第二個參數容許咱們將action做爲props綁定到組件中,mapDispatchToProps但願你返回包含對應action的object對象,例如:

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    increase: (...args) => dispatch(actions.increase(...args)),
    decrease: (...args) => dispatch(actions.decrease(...args))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(yourComponent)

當你想對組件的render更新進行更好的控制的時候,它也支持返回function方法,具體能夠點擊#279查看,例子:

const mapDispatchToProps = {
    // increment: () => increment(1),
    increase, // import increase function from action
    decrease 
}

mergeProps(stateProps, dispatchProps, ownProps) 該參數非必須,redux默認會幫你把更新維護一個新的props對象,相似調用Object.assign({}, ownProps, stateProps, dispatchProps)。

而options是爲了更好的定製化設置的一個參數,容許返回5個boolean、function的值,我平時基本上沒有接觸到,想了解的能夠參考api文檔。

附參考文檔:

  1. Redux中文文檔

  2. Redux api介紹

(本身平時寫的一些總結,有誤的地方歡迎交流指正)

相關文章
相關標籤/搜索