[note: 本文基於 React v15.3.0+ 進行討論]html
通常來講,編寫 React 組件的方式有如下三種:react
PureComponent
的組件;Component
的組件,這也是最常使用的組件形式。那麼,這三種形式的使用場景及優劣各是什麼呢?git
無狀態組件是經過函數定義的,好比下面這個最簡單的?:github
let Hello = (props) => <div>Hello {props.name}</div>
調用的時候,和日常組件的使用方式相同:redux
<Hello name="cjf" />
能夠看出,無狀態組件的最大特徵就是沒有內部狀態(廢話),因此無狀態組件的渲染結果徹底取決於輸入的 props
。數組
無狀態組件的優勢有如下幾個方面:less
缺點有如下兩點:函數
props
,它就會進行從新渲染。固然還有一點須要注意的是,無狀態組件對於 props
是淺比較的。PureComponent
的組件這類組件的定義方式以下:post
class MyComponent extends PureComponent {...}
PureComponent
是繼承於 Component
類的,不一樣的是內部實現了 shouldComponentUpdate
的優化。它會淺比較組件內部 props
和 state
的值,從而決定組件應不該該從新渲染,PureComponent
的使用能夠提升 React 應用的性能。性能
在 PureComponent
中,咱們不須要寫相似於
if (this.state.someVal !== computedVal) { this.setState({ someVal: computedVal }) }
的代碼來避免組件被重複渲染。
讓咱們看看源碼,
當一個組件是 PureComponent
時,會執行下面操做來檢查是否須要 update
:
if (type.prototype && type.prototype.isPureReactComponent) { return ( !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) ); }
這裏用的也是淺比較(shallowEqual
),因此對於多層嵌套的對象和數組中的變化都不會被檢測到。好比下面這個例子:
handleClick() { let { items } = this.state items.push('new-item') this.setState({ items }) } render() { return ( <div> <button onClick={::this.handleClick} /> <ItemList items={ this.state.items } /> </div> ) }
假設 ItemList
是一個 PureComponent
,由於它執行的是淺比較,因此 this.state.items
的變化是不會觸發 ItemList
的更新的。若是要觸發更新,應該使用 setState
的另外一種調用形式,每次都返回一個新的對象:
handleClick() { this.setState(prevState => ({ words: prevState.items.concat(['new-item']) })); }
最後須要注意的是,在 PureComponent
中是不能本身定義的 shouldComponentUpdate()
方法的。若是實在有這個必要,只能使用 Component
組件。
Component
的組件沒啥說的,這就是最普通的組件形式。
從上面的討論咱們能夠得出結論,在 React 應用中,應當儘量多的使用無狀態組件或 PureComponent
以加強複用性和提升性能。可是,在具體的項目實踐中,咱們每每須要經過 Ajax 請求獲取數據,並進一步對數據進行處理。爲了使組件的職責更加單一,引入了容器組件(Container Component)的概念。咱們能夠將數據獲取以及處理的邏輯放在容器組件中,而後將已處理的數據傳遞給展現組件,使得組件的耦合性進一步地下降。
react-redux 中的 connect()
就是容器組件的一種具體實現。