關於props和state以及redux中的state


  React的數據模型分為共有數據和私有數據,共有數據可以在組件間進行傳遞,私有數據為當前組件私有。共有數據在React中使用props對象來調用,它包含標簽所有的屬性名稱和屬性值,props對象有三個特性,單向流動性、顯示傳遞性和只讀性。單向流動性是指React的數據只能由父組件傳遞到子組件,而不能由子組件傳遞到父組件;顯示傳遞性是指必須明確地在子組件中通過屬性賦值,數據才可以傳遞到子組件;只讀性是指props數據是只讀的,數據修改后並未改變原始的數據模型,而是會新生成一份數據模型,並將新的數據模型加載到原始父元素,從而完成數據的傳遞和組件狀態的更改。私有數據為組件私有,在React使用state對象來調用,state數據模型可以方便地進行更新操作,並且不會影響到其他組件。

  需要理解的是,props是一個父組件傳遞給子組件的數據流,這個數據流可以一直傳遞到子孫組件。而state代表的是一個組件內部自身的狀態(可以是父組件、子孫組件)。改變一個組件自身狀態,從語義上來說,就是這個組件內部已經發生變化,有可能需要對此組件以及組件所包含的子孫組件進行重渲染。而props是父組件傳遞的參數,可以被用於顯示內容,或者用於此組件自身狀態的設置(部分props可以用來設置組件的state),不僅僅是組件內部state改變才會導致重渲染,父組件傳遞的props發生變化,也會執行。

  既然兩者的變化都有可能導致組件重渲染,所以只有理解props與state的意義,才能很好地決定到底什么時候用props或state。

  下面說一下react-redux中是如何維護state的,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('root')
)

  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。

  然后幾個問題:

  • React組件如何響應store的變化?
  • 為什么connect選擇性的merge一些props,而不是直接將整個state傳入?

  Connect的組件,它在包裝原有組件的基礎上,還在內部監聽了Redux的store的變化。

  但是通常,我們connect的是某個Container組件,它並不承載所有App state,然而我們的handler是響應所有state變化的,於是我們需要優化的是:當storeState變化的時候,僅在我們真正依賴那部分state變化時,才重新render相應的React組件,那么什么是我們真正依賴的部分?就是通過mapStateToPropsmapDispatchToProps得到的。具體優化的方式就是在shouldComponentUpdate中做檢查,如果只有在組件自身的props改變,或者mapStateToProps的結果改變,或者是mapDispatchToProps的結果改變時shouldComponentUpdate才會返回true,檢查的方式是進行shallowEqual的比較。

  關於connect的使用:

Then, we wrap the components we want to connect to Redux with connect() function from react-redux. Try to only do this for a top-level component, or route handlers. While technically you can connect() any component in your app to Redux store, avoid doing this too deeply because it will make the data flow harder to trace.

  Deep prop chains was one of the issues with React that led me to use Flux; the tradeoff for making it easier to trace the data flow is that you need to setup/maintain/trace the prop flow, and more importantly, parents need to know about the data requirements of their children.

  redux的作者說從技術上雖然允許連接任意組件,但是避免過多使用,否則數據流會很難追蹤,盡量只連接根組件,有開發者評論說redux如果只連接根組件,子組件嵌套過多,prop也會一級一級傳遞,很繁瑣,這應該也是redux一直被詬病的一點。

結語:所以redux中的state和組件自身維護的state並不是一個東西,每個組件本身有自己的state,但在Redux中,應用的狀態是全部存在一個單一的樹結構中的,換句話說,應用的所有狀態信息都存儲在這個包含map和array的數據結構中。一個Redux應用的狀態樹是不可變的數據結構。這意味着,一旦你得到了一棵狀態樹,它就不會在改變了。任何用戶行為改變應用狀態,你都會獲取一棵映射應用改變后新狀態的完整狀態樹。這說明任何連續的狀態(改變前后)都被分別存儲在獨立的兩棵樹。你通過調用一個函數來從一種狀態轉入下一個狀態。

 



 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM