首頁 > web前端 > js教程 > 主體

在React和Redux中有關連接react-redux(詳細教學)

亚连
發布: 2018-06-22 17:39:58
原創
1128 人瀏覽過

這篇文章主要介紹了淺談React和Redux的連接react-redux,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

之前一直在探索React相關的東西,手上有個SPA項目,於是準備上Redux試試水。 Redux本身和React並沒有之間的關聯,它是一個通用Javscript App模組,用做App State的管理。要在React的專案中使用Redux,比較好的方式是藉助react-redux這個函式庫來做連接,這裡的意思是,並不是沒有react-redux,這兩個函式庫就不弄一起用了,而是說react-redux提供了一些封裝,一種更科學的程式碼組織方式,讓我們更舒服地在React的程式碼中使用Redux。

之前僅透過Redux文件來了解react-redux,在一段時間的實踐後準備翻一翻原始碼,順便做些相關的總結。我看的程式碼的npm版本為v4.0.0,也就是說使用的React版本是0.14.x。

react-redux提供兩個關鍵模組:Provider和connect。

Provider

Provider這個模組是作為整個App的容器,在你原有的App Container的基礎上再包上一層,它的工作很簡單,就是接受Redux的store作為props,並將其聲明為context的屬性之一,子元件可以在聲明了contextTypes之後可以方便的透過this.context.store存取到store。不過我們的組件通常不需要這麼做,將store放在context裡,是為了給下面的connect用的。

這個是Provider的使用範例:

// config app root
const history = createHistory()
const root = (
 <Provider store={store} key="provider">
  <Router history={history} routes={routes} />
 </Provider>
)

// render
ReactDOM.render(
 root,
 document.getElementById(&#39;root&#39;)
)
登入後複製

connect

這個模組是算是真正意義上連接了Redux和React,剛好它的名字也叫connect。

先考慮Redux是怎麼運作的:首先store維護了一個state,我們dispatch一個action,接下來reducer根據這個action更新state。

對應到我們的React應用程式中,store中維護的state就是我們的app state,一個React元件作為View層,做兩件事:render和回應使用者操作。於是connect就是將store中的必要資料當作props傳遞給React元件來render,包裝action creator用於在回應使用者操作時dispatch一個action。

好了,詳細看看connect這個模組做了什麼。先從它的使用來說,它的API如下:

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
登入後複製

mapStateToProps是一個函數,回傳值表示的是需要merge進props的state。預設值為() => ({}),即什麼都不傳。

(state, props) => ({ }) // 通常会省略第二个参数
登入後複製

mapDispatchToProps是可以是一個函數,回傳值表示的是需要merge僅props的actionCreators,這裡的actionCreator應該是已經被包裝了dispatch了的,推薦使用redux的bindActionCreators函數。

(dispatch, props) => ({ // 通常会省略第二个参数
 ...bindActionCreators({
  ...ResourceActions
 }, dispatch)
})
登入後複製

更方便的是可以直接接受一個對象,此時connect函數內部會將其轉變為函數,這個函數和上面那個例子是一模一樣的。

mergeProps用於自訂merge流程,下面這個是預設流程,parentProps值的就是元件本身的props,可以發現如果元件的props上出現同名,會被覆寫。

(stateProps, dispatchProps, parentProps) => ({
 ...parentProps,
 ...stateProps,
 ...dispatchProps
})
登入後複製

options共有兩個開關:pure代表是否打開優化,詳細內容下面會提,預設為true,withRef用來給包裝在裡面的組件一個ref,可以透過getWrappedInstance方法來取得這個ref,預設為false。

connect傳回一個函數,它接受一個React元件的建構函數作為連接對象,最後傳回連接好的元件建構函數。

然後幾個問題:

  1. React元件如何回應store的變化?

  2. 為什麼connect選擇性的merge一些props,而不是直接將整個state傳入?

  3. pure優化的是什麼?

我們把connect回傳的函數叫做Connector,它回傳的是內部的一個叫Connect的元件,它在包裝原有元件的基礎上,還在內部監聽了Redux的store的變化,為了讓被它包裝的組件可以響應store的變化:

trySubscribe() {
 if (shouldSubscribe && !this.unsubscribe) {
  this.unsubscribe = this.store.subscribe(::this.handleChange)
  this.handleChange()
 }
}

handleChange () {
 this.setState({
  storeState: this.store.getState()
 })
}
登入後複製

但是通常,我們connect的是某個Container組件,它並不承載所有App state,然而我們的handler是響應所有state變化的,所以我們需要優化的是:當storeState變化的時候,只有在我們真正依賴那部分state變化時,才重新render對應的React元件,那麼什麼才是我們真正依賴的部分?就是透過mapStateToProps和mapDispatchToProps得到的。

具體優化的方式就是在shouldComponentUpdate中做檢查,如果只有在元件本身的props改變,或是mapStateToProps的結果改變,或是mapDispatchToProps的結果改變時shouldComponentUpdate才會回傳true,檢查的方式是shallowEqual的比較。

所以對某個reducer來說:

export default (state = {}, action) => {
 return { ...state } // 返回的是一个新的对象,可能会使组件reRender
 // return state // 可能不会使得组件reRender
}
登入後複製

另外在connect的時候,要謹慎map真正需要的state或actionCreators到props中,以避免不必要的效能損失。

最後,根據connect的API我們發現可以使用ES7 decorator功能來配合React ES6的寫法:

@connect(
 state => ({
  user: state.user,
  resource: state.resource
 }),
 dispatch => ({
  ...bindActionCreators({
   loadResource: ResourceActions.load
  }, dispatch)
 })
)
export default class Main extends Component {

}
登入後複製

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

有關JS排序演算法總結

使用JS canvas如何製作圓錐

在vue-router中如何實現路由懶載入

在Angular2中如何實作斷點偵錯ts檔案

如何實作網頁快報向上捲動

##在vue中有關資料夾結構配置

以上是在React和Redux中有關連接react-redux(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板