天天看點

React 實踐心得:react-redux 之 connect 方法詳解

React 實踐心得:react-redux 之 connect 方法詳解

redux 是「react 全家桶」中極為重要的一員,它試圖為 react 應用提供「可預測化的狀态管理」機制。redux 本身足夠簡單,除了 react,它還能夠支援其他界面架構。是以如果要将 redux 和 react 結合起來使用,就還需要一些額外的工具,其中最重要的莫過于 react-redux 了。

react-redux 提供了兩個重要的對象,<code>provider</code> 和 <code>connect</code>,前者使 react 元件可被連接配接(connectable),後者把 react 元件和 redux 的 store 真正連接配接起來。react-redux 的文檔中,對 <code>connect</code> 的描述是一段晦澀難懂的英文,在初學 redux 的時候,我對着這段文檔閱讀了很久,都沒有全部弄明白其中的意思(大概就是,單詞我都認識,連起來啥意思就不明白了的感覺吧)。

通過 <code>reducer</code> 建立一個 <code>store</code>,每當我們在 <code>store</code> 上 <code>dispatch</code> 一個 <code>action</code>,<code>store</code> 内的資料就會相應地發生變化。

我們當然可以直接在 react 中使用 redux:在最外層容器元件中初始化 <code>store</code>,然後将<code>state</code> 上的屬性作為 <code>props</code> 層層傳遞下去。

但這并不是最佳的方式。最佳的方式是使用 react-redux 提供的 <code>provider</code> 和 <code>connect</code> 方法。

首先在最外層容器中,把所有内容包裹在 <code>provider</code> 元件中,将之前建立的 <code>store</code> 作為<code>prop</code> 傳給 <code>provider</code>。

<code>provider</code> 内的任何一個元件(比如這裡的 <code>comp</code>),如果需要使用 <code>state</code> 中的資料,就必須是「被 connect 過的」元件——使用 <code>connect</code> 方法對「你編寫的元件(<code>mycomp</code>)」進行包裝後的産物。

可見,<code>connect</code> 方法是重中之重。

究竟 <code>connect</code> 方法到底做了什麼,我們來一探究竟。

首先看下函數的簽名:

connect([mapstatetoprops], [mapdispatchtoprops], [mergeprops], [options])

<code>connect()</code> 接收四個參數,它們分别是 <code>mapstatetoprops</code>,<code>mapdispatchtoprops</code>,<code>mergeprops</code>和<code>options</code>。

這個函數允許我們将 <code>store</code> 中的資料作為 <code>props</code> 綁定到元件上。

這個函數的第一個參數就是 redux 的 <code>store</code>,我們從中摘取了 <code>count</code> 屬性。因為傳回了具有 <code>count</code> 屬性的對象,是以 <code>mycomp</code> 會有名為 <code>count</code> 的 <code>props</code> 字段。

當然,你不必将 <code>state</code> 中的資料原封不動地傳入元件,可以根據 <code>state</code> 中的資料,動态地輸出元件需要的(最小)屬性。

函數的第二個參數 <code>ownprops</code>,是 <code>mycomp</code> 自己的 <code>props</code>。有的時候,<code>ownprops</code> 也會對其産生影響。比如,當你在 <code>store</code> 中維護了一個使用者清單,而你的元件 <code>mycomp</code> 隻關心一個使用者(通過 <code>props</code> 中的 <code>userid</code> 展現)。

當 <code>state</code> 變化,或者 <code>ownprops</code> 變化的時候,<code>mapstatetoprops</code> 都會被調用,計算出一個新的<code>stateprops</code>,(在與 <code>ownprops</code> merge 後)更新給 <code>mycomp</code>。

這就是将 redux <code>store</code> 中的資料連接配接到元件的基本方式。

<code>connect</code> 的第二個參數是 <code>mapdispatchtoprops</code>,它的功能是,将 action 作為 <code>props</code> 綁定到<code>mycomp</code> 上。

由于 <code>mapdispatchtoprops</code> 方法傳回了具有 <code>increase</code> 屬性和 <code>decrease</code> 屬性的對象,這兩個屬性也會成為 <code>mycomp</code> 的 <code>props</code>。

如上所示,調用 <code>actions.increase()</code> 隻能得到一個 <code>action</code> 對象 <code>{type:'increase'}</code>,要觸發這個 <code>action</code> 必須在 <code>store</code> 上調用 <code>dispatch</code> 方法。<code>diapatch</code> 正是 <code>mapdispatchtoprops</code> 的第一個參數。但是,為了不讓 <code>mycomp</code> 元件感覺到 <code>dispatch</code> 的存在,我們需要将 <code>increase</code> 和<code>decrease</code> 兩個函數包裝一下,使之成為直接可被調用的函數(即,調用該方法就會觸發<code>dispatch</code>)。

redux 本身提供了 <code>bindactioncreators</code> 函數,來将 action 包裝成直接可被調用的函數。

同樣,當 <code>ownprops</code> 變化的時候,該函數也會被調用,生成一個新的 <code>dispatchprops</code>,(在與<code>stateprope</code> 和 <code>ownprops</code> merge 後)更新給 <code>mycomp</code>。注意,<code>action</code> 的變化不會引起上述過程,預設 <code>action</code> 在元件的生命周期中是固定的。

之前說過,不管是 <code>stateprops</code> 還是 <code>dispatchprops</code>,都需要和 <code>ownprops</code> merge 之後才會被賦給 <code>mycomp</code>。<code>connect</code> 的第三個參數就是用來做這件事。通常情況下,你可以不傳這個參數,<code>connect</code> 就會使用 <code>object.assign</code> 替代該方法。

最後還有一個 <code>options</code> 選項,比較簡單,基本上也不大會用到(尤其是你遵循了其他的一些 react 的「最佳實踐」的時候),本文就略過了。希望了解的同學可以直接看文檔。

(完)

繼續閱讀