props和state之間的確切區別是什麼?理解它們的工做原理至關容易,尤爲是在上下文中查看時,可是從概念上理解它們也有些困難。一開始使人困惑,由於它們都具備抽象術語,而且它們的值看起來相同,可是它們也具備不一樣的做用。本文章同步發佈在個人博客:👉xueshiming.cn瀏覽器
setState()
會對一個組件的 state 對象安排一次更新。當 state
改變了,該組件就會從新渲染。bash
props(「properties」 的縮寫)
和 state
都是普通的 JavaScript
對象。它們都是用來保存信息的,這些信息能夠控制組件的渲染輸出,而它們的幾個重要的不一樣點就是:異步
props
是傳遞給組件的(相似於函數的形參),而 state
是在組件內被組件本身管理的(相似於在一個函數內聲明的變量)。函數
props
是不可修改的,全部 React
組件都必須像純函數同樣保護它們的 props
不被更改。 因爲 props
是傳入的,而且它們不能更改,所以咱們能夠將任何僅使用 props
的 React
組件視爲 pureComponent
,也就是說,在相同的輸入下,它將始終呈現相同的輸出。性能
state
是在組件中建立的,通常在 constructor
中初始化 state
ui
state
是多變的、能夠修改,每次setState
都異步更新的。this
在 React
中,this.props
和 this.state
都表明着已經被渲染了的值,即當前屏幕上顯示的值。spa
調用 setState
實際上是異步的 —— 不要期望在調用 setState
以後,this.state
會當即映射爲新的值。若是你須要基於當前的 state
來計算出新的值,那你應該傳遞一個函數,而不是一個對象(詳情見下文)。code
代碼不會像預期那樣運行的示例:對象
incrementCount() {
// 注意:這樣 *不會* 像預期的那樣工做。
this.setState({count: this.state.count + 1});
}
handleSomething() {
// 假設 `this.state.count` 從 0 開始。
this.incrementCount();
this.incrementCount();
this.incrementCount();
// 當 React 從新渲染該組件時,`this.state.count` 會變爲 1,而不是你指望的 3。
// 這是由於上面的 `incrementCount()` 函數是從 `this.state.count` 中讀取數據的,
// 可是 React 不會更新 `this.state.count`,直到該組件被從新渲染。
// 因此最終 `incrementCount()` 每次讀取 `this.state.count` 的值都是 0,並將它設爲 1。
// 問題的修復參見下面的說明。
}
複製代碼
那麼應該如何更新那些依賴於當前的
state
的state
呢?
給 setState
傳遞一個函數,而不是一個對象,就能夠確保每次的調用都是使用最新版的 state
。
給 setState 傳遞一個對象與傳遞一個函數的區別是什麼?
傳遞一個函數可讓你在函數內訪問到當前的 state
的值。由於 setState
的調用是分批的,因此你能夠鏈式地進行更新,並確保它們是一個創建在另外一個之上的,這樣纔不會發生衝突:
incrementCount() {
this.setState((state) => {
// 重要:在更新的時候讀取 `state`,而不是 `this.state`。
return {count: state.count + 1}
});
}
handleSomething() {
// 假設 `this.state.count` 從 0 開始。
this.incrementCount();
this.incrementCount();
this.incrementCount();
// 若是你如今在這裏讀取 `this.state.count`,它仍是會爲 0。
// 可是,當 React 從新渲染該組件時,它會變爲 3。
}
複製代碼
目前,在事件處理函數內部的 setState
是異步的。(V16.10)
例如,若是 Parent
和 Child
在同一個 click
事件中都調用了 setState
,這樣就能夠確保 Child
不會被從新渲染兩次。取而代之的是,React
會將該 state
等到瀏覽器事件結束的時候,再統一地進行更新。這種機制能夠在大型應用中獲得很好的性能提高。