redux中的connect函數

上面一篇文章,我們只是從Demo的角度講解了Redux,對於connect的部分,我們只是一筆帶過。

那麼我們這篇文章同樣是基於上一篇文章中的Demo,來從實戰的角度來詳細講解下connect方法。


connect方法聲明如下:

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

作用:連接 React 組件與 Redux store

連接操作不會改變原來的組件類,反而返回一個新的已與 Redux store 連接的組件類。


參數

[mapStateToProps(state, [ownProps]): stateProps] (Function): 如果定義該參數,組件將會監聽 Redux store 的變化。任何時候,只要 Redux store 發生改變,mapStateToProps 函數就會被調用。該回調函數必須返回一個純對象,這個對象會與組件的 props 合併。如果你省略了這個參數,你的組件將不會監聽 Redux store。如果指定了該回調函數中的第二個參數 ownProps,則該參數的值爲傳遞到組件的 props,而且只要組件接收到新的 props,mapStateToProps 也會被調用。


[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function): 如果傳遞的是一個對象,那麼每個定義在該對象的函數都將被當作 Redux action creator,而且這個對象會與 Redux store 綁定在一起,其中所定義的方法名將作爲屬性名,合併到組件的 props 中。如果傳遞的是一個函數,該函數將接收一個 dispatch 函數,然後由你來決定如何返回一個對象,這個對象通過 dispatch 函數與 action creator 以某種方式綁定在一起(提示:你也許會用到 Redux 的輔助函數 bindActionCreators())。如果你省略這個 mapDispatchToProps 參數,默認情況下,dispatch 會注入到你的組件 props 中。如果指定了該回調函數中第二個參數 ownProps,該參數的值爲傳遞到組件的 props,而且只要組件接收到新 props,mapDispatchToProps 也會被調用。


[mergeProps(stateProps, dispatchProps, ownProps): props] (Function): 如果指定了這個參數,mapStateToProps() 與 mapDispatchToProps() 的執行結果和組件自身的 props 將傳入到這個回調函數中。該回調函數返回的對象將作爲 props 傳遞到被包裝的組件中。你也許可以用這個回調函數,根據組件的 props 來篩選部分的 state 數據,或者把 props 中的某個特定變量與 action creator 綁定在一起。如果你省略這個參數,默認情況下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的結果。


[options] (Object) 如果指定這個參數,可以定製 connector 的行爲。

[pure = true] (Boolean): 如果爲 true,connector 將執行 shouldComponentUpdate 並且淺對比 mergeProps 的結果,避免不必要的更新,前提是當前組件是一個“純”組件,它不依賴於任何的輸入或 state 而只依賴於 props 和 Redux store 的 state。默認值爲 true。

[withRef = false] (Boolean): 如果爲 true,connector 會保存一個對被包裝組件實例的引用,該引用通過 getWrappedInstance() 方法獲得。默認值爲 false

返回值

根據配置信息,返回一個注入了 state 和 action creator 的 React 組件。


靜態屬性

WrappedComponent (Component): 傳遞到 connect() 函數的原始組件類。

靜態方法

組件原來的靜態方法都被提升到被包裝的 React 組件。

實例方法

getWrappedInstance(): ReactComponent

僅當 connect() 函數的第四個參數 options 設置了 { withRef: true } 才返回被包裝的組件實例。


備註:

1、 函數將被調用兩次。第一次是設置參數,第二次是組件與 Redux store 連接:connect(mapStateToProps, mapDispatchToProps, mergeProps)(MyComponent)。

2、 connect 函數不會修改傳入的 React 組件,返回的是一個新的已與 Redux store 連接的組件,而且你應該使用這個新組件。

3、 mapStateToProps 函數接收整個 Redux store 的 state 作爲 props,然後返回一個傳入到組件 props 的對象。該函數被稱之爲 selector。


=====================我是華麗麗的分割線=========================

我們開始通過代碼來講解。


[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. export default connect(mapStateToProps,mapDispatchToProps,mergeProps)(AddTodo);  

1、mapStateToProps

這個函數的作用是確定哪些 Redux 全局的 state 是我們組件想要通過 props 獲取的?


方法一:

//把整個state都返回,不建議這麼做

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. const mapStateToProps = (state)=> state;  

方法二:

//將state的部分返回

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. const mapStateToProps = (state)=>{  
  2.   return {  
  3.     num:state.num ,  
  4.     text:state.text,  
  5.   }  
  6. }  


2、mapDispatchToProps

這個方法的作用是確定 哪些 action 創建函數是我們想要通過 props 獲取的?


如果你省略這個 mapDispatchToProps 參數,默認情況下,dispatch 會注入到你的組件 props 中。

這也就是我們上一篇文章爲什麼可以直接從props中獲取dispatch。


我們先來看看我們的Action,定義了3個Action

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. export const addTodo = (num) => {  
  2.   return {  
  3.     type: 'INCREMENT',  
  4.     num: num,  
  5.   }  
  6. }  
  7.   
  8. export const decTodo = (num) => {  
  9.   return {  
  10.     type: 'DECREMENT',  
  11.     num: num,  
  12.   }  
  13. }  
  14.   
  15. export const updateText = (text) => {  
  16.   return {  
  17.     type: 'TEXT_UPDATE',  
  18.     text: text,  
  19.   }  
  20. }  


我們引入action 的方式有2種

方法一:

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. import { addTodo,decTodo,updateText } from '../actions’  

方法二:

//es5 不支持

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. import * as actionCreators from '../actions';  


我們需要導入 bindActionCreators

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. import { bindActionCreators } from 'redux';  

定義mapDispatchToProps函數也有2種方法

方法一:

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. const mapDispatchToProps = (dispatch)=>{  
  2.   return bindActionCreators(actionCreators,dispatch);  
  3.   
  4.    return {  
  5.      addTodo:bindActionCreators({ addTodo }, dispatch),  
  6.      decTodo:bindActionCreators({ decTodo }, dispatch),  
  7.      updateText:bindActionCreators({ updateText }, dispatch)  
  8.   }  
  9. }  

方法二:

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. const mapDispatchToProps = (dispatch)=>{  
  2.   // 此處直接返回,我們也可以設置一個key  
  3.   //  actions:bindActionCreators(actionCreators,dispatch);  
  4.    
  5.   return bindActionCreators(actionCreators,dispatch);  
  6. }  


3、mergeProps

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. function mergeProps(stateProps, dispatchProps, ownProps) {  
  2.   return Object.assign({}, ownProps, stateProps, dispatchProps);  
  3. }  

如果你省略這個參數,默認情況下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的結果。

通常情況下,我們都需要修改這個函數。

那麼我們的View也需要變動

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <TouchableHighlight style={styles.itemView} underlayColor="red" onPress={()=>this.props.addTodo(1)}>  
  2.     <Text style={styles.itemText}>  
  3.       點擊我就+1  
  4.     </Text>  
  5. </TouchableHighlight>  

此時:

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. onPress={()=>{dispatch(addTodo(1))}}  

變爲

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. onPress={()=>this.props.addTodo(1)}  

從props中獲取Action(addTodo)。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章