和 Flux 相似,Redux 也是須要註冊一個回調函數 store.subscribe(listener)
來獲取 State 的更新,而後咱們要在 listener
裏面調用 setState()
來更新 React 組件。javascript
Redux 官方提供了 react-redux 來簡化 React 和 Redux 之間的綁定,再也不須要像 Flux 那樣手動註冊/解綁回調函數。html
接下來看一下是怎麼作到的,react-redux 只有兩個 APIjava
<Provider>
做爲一個容器組件,用來接受 Store,而且讓 Store 對子組件可用,用法以下:react
import { render } from 'react-dom'; import { Provider } from 'react-redux'; import App from './app'; render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
這時候 <Provider>
裏面的子組件 <App />
纔可使用 connect
方法關聯 store。git
<Provider>
的實現很簡單,他利用了 React 一個(暫時)隱藏的特性 Contexts
,Context
用來傳遞一些父容器的屬性對全部子孫組件可見,在某些場景下面避免了用 props
傳遞多層組件的繁瑣,要想更詳細瞭解 Contexts
能夠參考這篇文章。github
connect()
這個方法略微複雜一點,主要是由於它的用法很是靈活:connect([mapStateToProps], mapDispatchToProps], [mergeProps], [options])
,它最多接受4個參數,都是可選的,而且這個方法調用會返回另外一個函數,這個返回的函數來接受一個組件類做爲參數,最後才返回一個和 Redux store 關聯起來的新組件,相似這樣:redux
class App extends Component { ... } export default connect()(App);
這樣就能夠在 App
這個組件裏面經過 props
拿到 Store 的 dispatch
方法,可是注意如今的 App
沒有監聽 Store 的狀態更改,若是要監聽 Store 的狀態更改,必需要指定 mapStateToProps
參數。api
先來看它的參數:app
[mapStateToProps(state, [ownProps]): stateProps]
: 第一個可選參數是一個函數,只有指定了這個參數,這個關聯(connected)組件纔會監聽 Redux Store 的更新,每次更新都會調用 mapStateToProps
這個函數,返回一個字面量對象將會合併到組件的 props
屬性。 ownProps
是可選的第二個參數,它是傳遞給組件的 props
,當組件獲取到新的 props
時,ownProps
都會拿到這個值而且執行mapStateToProps
這個函數。[mapDispatchProps(dispatch, [ownProps]): dispatchProps]
: 這個函數用來指定如何傳遞 dispatch
給組件,在這個函數裏面直接 dispatch action creator,返回一個字面量對象將會合併到組件的 props
屬性,這樣關聯組件能夠直接經過 props
調用到 action
, Redux 提供了一個bindActionCreators()
輔助函數來簡化這種寫法。 若是省略這個參數,默認直接把 dispatch
做爲props
傳入。ownProps
做用同上。剩下的兩個參數比較少用到,更詳細的說明參看官方文檔,其中提供了不少簡單清晰的用法示例來講明這些參數。dom
Redux 建立 Store,Action,Reducer 這部分就省略了,這裏只看 react-redux 的部分。
import React, { Component } from 'react'; import someActionCreator from './actions/someAction'; import * as actionCreators from './actions/otherAction'; function mapStateToProps(state) { return { propName: state.propName }; } function mapDispatchProps(dispatch) { return { someAction: (arg) => dispatch(someActionCreator(arg)), otherActions: bindActionCreators(actionCreators, dispatch) }; } class App extends Component { render() { // `mapStateToProps` 和 `mapDispatchProps` 返回的字段都是 `props` const { propName, someAction, otherActions } = this.props; return ( <div onClick={someAction.bind(this, 'arg')}> {propName} </div> ); } } export default connect(mapStateToProps, mapDispatchProps)(App);
如前所述,這個 connected 的組件必須放到 <Provider>
的容器裏面,當 State 更改的時候就會自動調用mapStateToProps
和 mapDispatchProps
從而更新組件的 props
。 組件內部也能夠經過 props
調用到 action,若是沒有省略了 mapDispatchProps
,組件要觸發 action 就必須手動 dispatch,相似這樣:this.props.dispatch(someActionCreator('arg'))
。