轉載自 Dan Abramov. Presentational and Container Components. Mar 23, 2015html
2019年更新:我在好久之前寫了這篇文章,但後來個人觀點發生了變化。特別是,我不建議再像這樣拆分你的組件。若是你以爲在你的代碼庫中這樣寫很天然,這種模式能夠很方便。但我已經看到它在沒有任何須要的狀況下被強制執行,並且幾乎是教條式的狂熱,次數太多了。我發現它有用的主要緣由是,它讓我把複雜的有狀態邏輯從組件的其餘方面分離出來。Hooks讓我作了一樣的事情並且沒有任意的劃分。因爲歷史緣由,我完整地保留了這段文字,但不要太當真。react
在編寫React應用時,有一個簡單的模式我以爲很是有用。若是你已經作了一段時間的React,你可能已經發現了它。這篇文章很好地解釋了它,但我想再補充幾點。 若是你把你的組件分爲兩類,你會發現你的組件更容易重用和推理。我把它們稱爲容器Container
和展現Presentational
型組件*,但我也據說過 Fat 和 Skinny,Smart 和 Dumb,Stateful和 Pure,Screen 和 Component等。這些都不徹底相同,不過核心思想是類似的。git
this.props.children
進行包含。爲presentational或其餘容器組件提供數據和行爲。github
connect()
、Relay的createContainer()
或Flux Utils的Container.create()
,而不是手工編寫。我把它們放在不一樣的文件夾裏,以明確這種區別。web
展現型組件本質上就是你的應用的 "調色板"。你能夠把它們放在一個頁面上,讓設計師調整它們的全部變化,而不觸及應用的邏輯。你能夠在該頁面上運行截圖迴歸測試。redux
this.props.children
,而不是在幾個容器組件中重複相同的標記和佈局。請記住,組件不必定要操做DOM。它們只須要提供UI關注點之間的組成邊界。 利用好這一點。數組
我建議你先只用展現組件開始構建你的應用。最終你會意識到,你把太多的道具傳遞給了中間的組件。當你注意到有些組件並無使用它們接收到的道具,而只是將它們轉發下去,並且當子組件須要更多數據時,你必須隨時從新鏈接全部這些中間組件,這就是引入一些容器組件的好時機。這樣你就能夠把數據和行爲道具送到葉子組件上,而不會給樹中間的不相關組件形成負擔。 這是一個不斷重構的過程,因此不要試圖第一次就把它作好。當你嘗試這種模式時,你會對何時該提取一些容器有一種直觀的感受,就像你知道何時該提取一個函數同樣。個人free Redux Egghead系列或許也能幫到你!性能優化
重要的是,你要明白,展現性組件和容器之間的區別不是技術上的區別。而是它們的目的的區別。 相比之下,這裏有幾個相關(但不一樣!)的技術區別。markdown
有狀態和無狀態。有些組件使用React setState()
方法,有些不使用。雖然容器組件傾向於有狀態,而呈現型組件傾向於無狀態,但這並非一個硬性規則。呈現型組件能夠是有狀態的,容器也能夠是無狀態的。ide
類和函數。從React 0.14開始,組件既能夠聲明爲類,也能夠聲明爲函數。函數式組件的定義更簡單,但它們缺少某些目前只有類組件纔有的功能。其中一些限制可能會在將來消失,但它們今天仍然存在。由於功能組件更容易理解,我建議你使用它們,除非你須要狀態、生命週期鉤子或性能優化,這些功能目前只有類組件纔有。
純粹和不純粹。人們說,若是一個組件能保證在相同的道具和狀態下返回相同的結果,那麼這個組件就是純粹的。純組件既能夠定義爲類,也能夠定義爲函數,既能夠有狀態,也能夠無狀態。純組件的另外一個重要方面是它們不依賴於道具或狀態的深度突變,所以它們的渲染性能能夠經過在其shouldComponentUpdate()
鉤子中進行淺層比較來優化。目前只有類能夠定義shouldComponentUpdate()
,但將來可能會改變。
呈現型組件和容器均可以納入這兩種類型。根據個人經驗,呈現型組件每每是無狀態的純函數,而容器每每是有狀態的純類。然而這並非一個規則,而是一個觀察結果,我也看到過在特定狀況下徹底相反的狀況,這是有道理的。 不要把有狀態和容器組件分離當成教條。有時候這並不重要,或者說很難劃清界限。若是你以爲不肯定某個特定的組件應該是呈現性的仍是容器的,那麼如今決定可能還爲時過早。沒關係張!
This gist by Michael Chan pretty much nails it.
Getting Started with Redux Mixins are Dead, Long Live Composition Container Components Atomic Web Design Building the Facebook News Feed with Relay
- 在本文的早期版本中,我把它們稱爲 "Smart"和 "Dumb"的組件,但這對展現組件來講過於苛刻,並且最重要的是,沒有真正解釋它們的目的的差別。我更喜歡這個新的術語,我但願你也是如此
** 在本文的早期版本中,我聲稱展現性組件應該只包含其餘展現性組件。我再也不認爲這是事實。一個組件是展現型組件仍是容器屬於它的實現細節。你應該可以在不修改任何調用站點的狀況下,用容器替換一個展現型組件。所以,展現型組件和容器組件均可以包含其餘展現型組件或容器組件就行了。