在上一篇中寫過,組件能夠分爲函數式組件和類組件,而且更新組件的方法也給出了經過傳入ReactDOM.render()方法進行更新。可是這種方式並不能很好地進行封裝成獨立功能的組件,一些操做會由外部進行控制。而咱們理想中的組件應該是一個功能獨立的個體,只是不一樣場合不一樣的數據纔會出現不一樣。
而這就就關聯到了咱們此次的主題---狀態(State)
狀態(state) 和 屬性(props) 相似,都是一個組件所須要的一些數據集合,可是它是私有的,而且由組件自己徹底控制,能夠認爲它是組件的「私有屬性(或者是局部屬性)」。數組
若是想要使用狀態(State)的話,則須要咱們在構建組件的時候是要以類組件爲形式的。
針對直接以類組件形式構造的組件不須要變化,那麼針對函數式組件該如何轉化呢?異步
例如:函數
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } }
上面示例就是一個簡單的類組件Clock。性能
1) 替換 render() 方法中的 this.props.date 爲 this.state.date:優化
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
2) 添加一個 類構造函數(class constructor) 初始化 this.state:this
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
❤ 注意咱們如何將 props 傳遞給基礎構造函數:
constructor(props) { super(props); *** this.state = {date: new Date()}; }
3) 移除 <Clock /> 元素中的 date 屬性:code
ReactDOM.render( <Clock />, document.getElementById('root') );
經過上面的步驟就能夠實現添加State到類組件了,最終結果:component
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
State的初始化和常規的賦值形式是同樣的,可是若是咱們須要更新相關數據的話,則須要經過setState方法進行修改,如:對象
this.setState({ date: new Date() });
關於如何正確使用State以及setState() 有三個方面須要注意:繼承
正如上面提到的如何修改State那樣,在初始化後,若是修改的話只能經過setState方法進行修改。
React 爲了優化性能,有可能會將多個 setState() 調用合併爲一次更新。
由於 this.props 和 this.state 多是異步更新的,你不能依賴他們的值計算下一個state(狀態)。
如:
// 錯誤 this.setState({ counter: this.state.counter + this.props.increment, });
要彌補這個問題,使用另外一種 setState() 的形式,它接受一個函數而不是一個對象。這個函數將接收前一個狀態做爲第一個參數,應用更新時的 props 做爲第二個參數:
// 正確 this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));
當你調用 setState(), React 將合併你提供的對象到當前的狀態中。因此當State是一個多鍵值的結構時,能夠單獨更新其中的一個,此時會進行「差分」更新,不會影響其餘的屬性值。
生命週期就是指一個對象的生老病死。
而組件的生命週期則是這個組件從建立到銷燬的一個過程。在這個過程當中會有不一樣的階段,從而會產生一些對應的生命週期函數來供咱們使用,以便可以進行一些渲染、更新等處理。
能夠簡單分爲幾個階段:
初始化階段
運行中狀態
銷燬階段
不管做爲父組件仍是子組件,它都沒法獲悉一個組件是否有狀態,同時也不須要關心另外一個組件是定義爲函數組件仍是類組件。
這就是 state(狀態) 常常被稱爲 本地狀態 或 封裝狀態的緣由。 它不能被擁有並設置它的組件 之外的任何組件訪問。
一個組件能夠選擇將 state(狀態) 向下傳遞,做爲其子組件的 props(屬性):
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
這一般稱爲一個「從上到下」,或者「單向」的數據流。任何 state(狀態) 始終由某個特定組件全部,而且從該 state(狀態) 導出的任何數據 或 UI 只能影響樹中 「下方」 的組件。
若是把組件樹想像爲 props(屬性) 的瀑布,全部組件的 state(狀態) 就如同一個額外的水源匯入主流,且只能隨着主流的方向向下流動。
在 React 應用中,一個組件是不是有狀態或者無狀態的,被認爲是組件的一個實現細節,隨着時間推移可能發生改變。你能夠在有狀態的組件中使用無狀態組件,反之亦然。