摘要:傳入一個對象的時候,這個對象表示該組件的新狀態(tài)。下一節(jié)中我們將介紹小書配置組件的。
React.js 小書 Lesson10 - 組件的 state 和 setState
本文作者:胡子大哈
本文原文:http://huziketang.com/books/react/lesson10
轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息
在線閱讀:http://huziketang.com/books/react
state我們前面提到過,一個組件的顯示形態(tài)是可以由它數(shù)據(jù)狀態(tài)和配置參數(shù)決定的。一個組件可以擁有自己的狀態(tài),就像一個點贊按鈕,可以有“已點贊”和“未點贊”狀態(tài),并且可以在這兩種狀態(tài)之間進(jìn)行切換。React.js 的 state 就是用來存儲這種可變化的狀態(tài)的。
我們還是拿點贊按鈕做例子,它具有已點贊和未點贊兩種狀態(tài)。那么就可以把這個狀態(tài)存儲在 state 中。修改 src/index.js 為:
import React, { Component } from "react" import ReactDOM from "react-dom" import "./index.css" class LikeButton extends Component { constructor () { super() this.state = { isLiked: false } } handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) } render () { return ( ) } } ...
isLiked 存放在實例的 state 對象當(dāng)中,這個對象在構(gòu)造函數(shù)里面初始化。這個組件的 render 函數(shù)內(nèi),會根據(jù)組件的 state 的中的isLiked不同顯示“取消”或“點贊”內(nèi)容。并且給 button 加上了點擊的事件監(jiān)聽。
最后構(gòu)建一個 Index ,在它的 render 函數(shù)內(nèi)使用 LikeButton 。然后把 Index 渲染到頁面上:
... class Index extends Component { render () { return (setState 接受對象參數(shù)) } } ReactDOM.render(, document.getElementById("root") )
在 handleClickOnLikeButton 事件監(jiān)聽函數(shù)里面,大家可以留意到,我們調(diào)用了 setState 函數(shù),每次點擊都會更新 isLiked 屬性為 !isLiked,這樣就可以做到點贊和取消功能。
setState 方法由父類 Component 所提供。當(dāng)我們調(diào)用這個函數(shù)的時候,React.js 會更新組件的狀態(tài) state ,并且重新調(diào)用 render 方法,然后再把 render 方法所渲染的最新的內(nèi)容顯示到頁面上。
注意,當(dāng)我們要改變組件的狀態(tài)的時候,不能直接用 this.state = xxx 這種方式來修改,如果這樣做 React.js 就沒辦法知道你修改了組件的狀態(tài),它也就沒有辦法更新頁面。所以,一定要使用 React.js 提供的 setState 方法,它接受一個對象或者函數(shù)作為參數(shù)。
傳入一個對象的時候,這個對象表示該組件的新狀態(tài)。但你只需要傳入需要更新的部分就可以了,而不需要傳入整個對象。例如,假設(shè)現(xiàn)在我們有另外一個狀態(tài) name :
... constructor (props) { super(props) this.state = { name: "Tomy", isLiked: false } } handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) } ...
因為點擊的時候我們并不需要修改 name,所以只需要傳入 isLiked 就行了。Tomy 還是那個 Tomy,而 isLiked 已經(jīng)不是那個 isLiked 了。
setState 接受函數(shù)參數(shù)這里還有要注意的是,當(dāng)你調(diào)用 setState 的時候,React.js 并不會馬上修改 state。而是把這個對象放到一個更新隊列里面,稍后才會從隊列當(dāng)中把新的狀態(tài)提取出來合并到 state 當(dāng)中,然后再觸發(fā)組件更新。這一點要好好注意??梢泽w會一下下面的代碼:
... handleClickOnLikeButton () { console.log(this.state.isLiked) this.setState({ isLiked: !this.state.isLiked }) console.log(this.state.isLiked) } ...
你會發(fā)現(xiàn)兩次打印的都是 false,即使我們中間已經(jīng) setState 過一次了。這并不是什么 bug,只是 React.js 的 setState 把你的傳進(jìn)來的狀態(tài)緩存起來,稍后才會幫你更新到 state 上,所以你獲取到的還是原來的 isLiked。
所以如果你想在 setState 之后使用新的 state 來做后續(xù)運算就做不到了,例如:
... handleClickOnLikeButton () { this.setState({ count: 0 }) // => this.state.count 還是 undefined this.setState({ count: this.state.count + 1}) // => undefined + 1 = NaN this.setState({ count: this.state.count + 2}) // => NaN + 2 = NaN } ...
上面的代碼的運行結(jié)果并不能達(dá)到我們的預(yù)期,我們希望 count 運行結(jié)果是 3 ,可是最后得到的是 NaN。但是這種后續(xù)操作依賴前一個 setState 的結(jié)果的情況并不罕見。
這里就自然地引出了 setState 的第二種使用方式,可以接受一個函數(shù)作為參數(shù)。React.js 會把上一個 setState 的結(jié)果傳入這個函數(shù),你就可以使用該結(jié)果進(jìn)行運算、操作,然后返回一個對象作為更新 state 的對象:
... handleClickOnLikeButton () { this.setState((prevState) => { return { count: 0 } }) this.setState((prevState) => { return { count: prevState.count + 1 } // 上一個 setState 的返回是 count 為 0,當(dāng)前返回 1 }) this.setState((prevState) => { return { count: prevState.count + 2 } // 上一個 setState 的返回是 count 為 1,當(dāng)前返回 3 }) // 最后的結(jié)果是 this.state.count 為 3 } ...
這樣就可以達(dá)到上述的利用上一次 setState 結(jié)果進(jìn)行運算的效果。
setState 合并上面我們進(jìn)行了三次 setState,但是實際上組件只會重新渲染一次,而不是三次;這是因為在 React.js 內(nèi)部會把 JavaScript 事件循環(huán)中的消息隊列的同一個消息中的 setState 都進(jìn)行合并以后再重新渲染組件。
深層的原理并不需要過多糾結(jié),你只需要記住的是:在使用 React.js 的時候,并不需要擔(dān)心多次進(jìn)行 setState 會帶來性能問題。
下一節(jié)中我們將介紹《React.js 小書 Lesson11 - 配置組件的 props》。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/89664.html
摘要:一個組件的顯示形態(tài)由多個狀態(tài)決定的情況非常常見。我們順利地消除了手動的操作。非一般的暴力,因為每次都重新構(gòu)造新增刪除元素,會導(dǎo)致瀏覽器進(jìn)行大量的重排,嚴(yán)重影響性能。下一節(jié)小書前端組件化三抽象出公共組件類我們把這個通用模式抽離到一個類當(dāng)中。 React.js 小書 Lesson3 - 前端組件化(二):優(yōu)化 DOM 操作 本文作者:胡子大哈本文原文:http://huziketang....
摘要:例如,上面設(shè)置了的為,在中被初始化為空字符串。如何向傳遞的數(shù)據(jù)父組件只需要通過給子組件傳入一個回調(diào)函數(shù)。當(dāng)用戶點擊發(fā)布按鈕的時候,調(diào)用中的回調(diào)函數(shù)并且將傳入該函數(shù)即可。下一節(jié)中我們將介紹小書實戰(zhàn)分析評論功能三。 React.js 小書 Lesson15 - 實戰(zhàn)分析:評論功能(二) 本文作者:胡子大哈本文原文:http://huziketang.com/books/react/les...
摘要:多次的隱藏和顯示會讓重新構(gòu)造和銷毀組件,每次構(gòu)造都會重新構(gòu)建一個定時器。而銷毀組件的時候沒有清除定時器,所以你看到報錯會越來越多。例如清除該組件的定時器和其他的數(shù)據(jù)清理工作。下一節(jié)中我們將介紹小書更新階段的組件生命周期。 React.js 小書 Lesson19 - 掛載階段的組件生命周期(二) 本文作者:胡子大哈本文原文:http://huziketang.com/books/re...
摘要:最后抽離出來了一個類,可以幫助我們更好的做組件化。一個組件有自己的顯示形態(tài)上面的結(jié)構(gòu)和內(nèi)容行為,組件的顯示形態(tài)和行為可以由數(shù)據(jù)狀態(tài)和配置參數(shù)共同決定。接下來我們開始正式進(jìn)入主題,開始正式介紹。下一節(jié)鏈接直達(dá)小書基本環(huán)境安裝 React.js 小書 Lesson4 - 前端組件化(三):抽象出公共組件類 本文作者:胡子大哈本文原文:http://huziketang.com/books...
摘要:默認(rèn)配置上面的組件默認(rèn)配置我們是通過操作符來實現(xiàn)。但這并不意味著由決定的顯示形態(tài)不能被修改。組件可以在內(nèi)部通過獲取到配置參數(shù),組件可以根據(jù)的不同來確定自己的顯示形態(tài),達(dá)到可配置的效果。下一節(jié)中我們將介紹小書。 React.js 小書 Lesson11 - 配置組件的 props 本文作者:胡子大哈本文原文:http://huziketang.com/books/react/lesso...
閱讀 5353·2021-09-22 15:50
閱讀 1905·2021-09-02 15:15
閱讀 1193·2019-08-29 12:49
閱讀 2570·2019-08-26 13:31
閱讀 3488·2019-08-26 12:09
閱讀 1239·2019-08-23 18:17
閱讀 2765·2019-08-23 17:56
閱讀 2959·2019-08-23 16:02