Redux要解決什么問題?
隨著 JavaScript 單頁應用開發(fā)日趨復雜,JavaScript 需要管理比任何時候都要多的 state (狀態(tài))。 這些 state 可能包括服務器響應、緩存數(shù)據(jù)、本地生成尚未持久化到服務器的數(shù)據(jù),也包括 UI 狀態(tài),如激活的路由,被選中的標簽,是否顯示加載動效或者分頁器等等。
管理不斷變化的 state 非常困難。如果一個 model 的變化會引起另一個 model 變化,那么當 view 變化時,就可能引起對應 model 以及另一個 model 的變化,依次地,可能會引起另一個 view 的變化。直至你搞不清楚到底發(fā)生了什么。state 在什么時候,由于什么原因,如何變化已然不受控制。 當系統(tǒng)變得錯綜復雜的時候,想重現(xiàn)問題或者添加新功能就會變得舉步維艱。
Redux的設計借鑒Flux、 Elm、Immutable,它的出現(xiàn)就是為了解決state里的數(shù)據(jù)問題。Redux和Flux的主要區(qū)別是Redux里面是單一的數(shù)據(jù)源設計,而Flux(或者Reflux)里面有多個數(shù)據(jù)源。
Redux是如何工作的?
我們知道,在React中,數(shù)據(jù)在組件中是單向流動的。數(shù)據(jù)從一個方向父組件流向子組件(通過props),由于這個特征,兩個非父子關系的組件(或者稱作兄弟組件)之間的通信并不是那么清楚。
React并不建議直接采用組件到組件的通信方式,盡管它有一些特性可以支持這么做(比如先將子組件的值傳遞給父組件,然后再由父組件在分發(fā)給指定的子組件)。這被很多人認為是糟糕的實踐方式,因為這樣的方式容易出錯而且會讓代碼向“拉面”一樣不容易理解。
當然React也沒有直接建議如何去處理這種情形,以下是React的文檔中關于這部分的描述:
對于非父子關系的組件,你可以自己建立一個全局的事件系統(tǒng),F(xiàn)lux的模式也是一種可行的方式。
Redux的出現(xiàn)就讓這個問題的解決變得更加方便了。Redux提供一種存儲整個應用狀態(tài)到一個地方的解決方案(可以理解為統(tǒng)一狀態(tài)層),稱為“store”,組件將狀態(tài)的變化轉(zhuǎn)發(fā)通知(dispatch)給store,而不是直接通知其它的組件。組件內(nèi)部依賴的state的變化情況可以通過訂閱store來實現(xiàn)。
使用Redux,所有的組件都從store里面獲取它們依賴的state,同時也需要將state的變化告知store。組件不需要關注在這個store里面其它組件的state的變化情況,Redux讓數(shù)據(jù)流變得更加簡單。這種思想最初來自Flux,它是一種和React相同的單向數(shù)據(jù)流的設計模式。