Written by Neil Fenton16 June 2016
原文請見

React和Redux組合是非常棒的,當他們兩個一起使用時,可以幫助我們在程序結(jié)構(gòu)中分離關注點.即使React易用性非常強,但是總會遇到高性能需求的時間.
在React中最昂貴的操作就是渲染回路.當組件檢測到輸入的變化,渲染回路就會被觸發(fā)(譯注:這里的意思的組件的action會改變redux的state,變回最終又回到組件了).
當我們初次開始React程序的時候,我們不會擔心渲染回路的花銷問題.但是當我們的UI變得復雜的時候,我們需要考慮這一點.React提供了一些工具讓我們能劫持渲染回路,如果渲染看上去不必要,我們就可以使用工具來阻止重渲染的發(fā)生.為了這么做,我們要敲入componentShouldUpdate生命周期事件,返回一個布爾值,通知組件是否應該進行更新.這是以PureRenderMixin作為基礎,它比較輸入的props和state和先前的props和state,如果兩者相等就返回false.
這個生命周期事件和Immutable集合一起可以實實在在的改進性能,因為我們可以很容易的決定是渲染還是不渲染組件.
不幸的是,僅此而已.
考慮到緊接著的問題:我們構(gòu)建一個購物車,有三個輸入類型:
- 購物車里的貨物
- 貨物的數(shù)量
- 相應的稅率(基于州或者省)
問題是無論只要輸入的狀態(tài)一改變(新貨物加入,數(shù)量的變化,選擇州的變哈),每一個部分都要被重新計算和渲染.如果我們的購物車里有幾百個東西,你可以想象一下這將會是一個很大的性能問題.改變稅率肯能會觸發(fā)購物車的重新計算,但是是不應該發(fā)生的.稅率的變化僅僅會影響衍生的數(shù)據(jù).僅僅總數(shù),稅的總數(shù)應該發(fā)生變化,并且發(fā)生后繼的更新.接下來我們看看怎么修復這個問題.(譯注:這段的意思是如果稅率變化,在UI組件中是不應該發(fā)生渲染的,只有幾個地方需要發(fā)生變化)
Reselect前來救援
Reselect用來記憶selectors的庫.我們定義的selectors是作為函數(shù)獲取Redux state的某一部分.使用記憶能力,我們可以組織不必要的衍生數(shù)據(jù)的重渲染和計算過程,由此加速了我們的app.
考慮下面這個示例:
如果我們有幾百甚至上千個條目,渲染購物車中的所有項目花費會非常的大,即使是稅率的變化.用戶每一次搜索的他的購物車的時候,我們是否應該一遍一遍的重計算?我們可以使用記憶性的selectors來阻止昂貴的計算過程.使用記憶selectors,如果Redux中的state的樹很大,我們也不用擔心沒吃state變化的計算問題.我們也可以在前端增加額外的靈活性,把這些selectors分散到單個的組件中.
現(xiàn)在看看一個使用Reselect的簡單selector:

在上面的實例中,我們把item的獲取函數(shù)分成兩個函數(shù),第一個函數(shù)(第3行)簡單的額獲取購物車中所有的items,第二個函數(shù)代表一個記憶性selector.Reselect暴露了createSelectorAPI,我們可以借此創(chuàng)建一個記憶性的selector.這個意思是getItemWithTotals在第一次函數(shù)運行的時候?qū)M行運算.如果同一個函數(shù)再次被調(diào)用,但是輸入值(getItems的值)沒有變化,函數(shù)將會返回一個緩存(cached)的計算結(jié)果.如果items被修改了(例如:item添加,數(shù)量的變化,任何事情操作了getItems的結(jié)果),函數(shù)將會再次執(zhí)行.
這是一個非常有力的概念,允許我們在一個組件的state需要重計算的時候,完全的優(yōu)化應該被渲染的組件.這意味著我們不在擔心getItems和后繼的每一次中價格的計算,但操作的時候,不會影響state的執(zhí)行.
我們繼續(xù)這個方式來創(chuàng)建四個衍生數(shù)據(jù)的selectors.包括小計,稅額總計和總價格.

使用selector
selectors代碼完成以后,讓我們看看怎么在組件中使用getItemWithTitalsselector:
現(xiàn)在我們有了有了一個組件,僅僅感知購物車中的items.這是一個不錯的方式因為它和總計和小計沒有任何關聯(lián).他不是可以重用的組件,但是是性能非常好的組件.和這個組件無關的變化不會引起額外的重渲染.
這個方式應用到其他的購物車上意味著我們將會有一個組件負責顯示小計,總計和稅額計算.
早一點在應用中使用這些優(yōu)化措施意味著未來需要修正性能問題的時候做的工作就比較少.我建議盡可能早的使用reselect.在組件之外使用Selectors意味著我們可以容易的測試這些數(shù)據(jù)衍生計算.在Redux中使用簡單的模擬數(shù)據(jù),基于提供的數(shù)據(jù)測試期待的輸出結(jié)果.
進一步了解這些概念,參考demo