摘要:組件狀態(tài)是一種持有,處理和使用信息的方式。更新唯一你能直接寫的地方應(yīng)該是組件的構(gòu)造函數(shù)中。是異步的事實上會引起的一致性處理重新渲染組件樹的過程,是下一個屬性的基礎(chǔ)即是異步的。常見錯誤其中最常見的錯誤之一就是在構(gòu)造函數(shù)中使用設(shè)置的值。
組件狀態(tài)(state)是一種持有,處理和使用信息的方式。state包含的信息僅作用于一個給定組件的內(nèi)部,并允許你根據(jù)它實現(xiàn)組件的一些邏輯。state通常是一個POJO(Plain Old Java[Script] Object)對象,改變它是使得組件重新render自己的方式之一。
state是react背后原理的重要基礎(chǔ)概念之一,但是它也有一些特點使得它用起來會有點難以捉摸并且有可能會導(dǎo)致在你的應(yīng)用中出現(xiàn)一些預(yù)料之外的行為。
更新State
唯一你能直接寫this.state的地方應(yīng)該是組件的構(gòu)造函數(shù)中。在其它所有地方你都應(yīng)該使用this.setState函數(shù),它接受一個對象作為參數(shù),這個對象最終會被合并到組件的當(dāng)前狀態(tài)中。
而在技術(shù)上你是可以通過this.state={//a new object}這種方式直接修改狀態(tài)的,但是它不會引起組件使用新的值去重新渲染,然后導(dǎo)致狀態(tài)不一致的問題。
setState是異步的
事實上setState會引起的一致性處理(reconciliation)——重新渲染組件樹的過程,是下一個屬性的基礎(chǔ)即setState是異步的。這允許我們在單個作用域內(nèi)多次調(diào)用setState而不會觸發(fā)不必要的重新渲染整個樹。
這就是為什么在你更新state后并不能立馬看見新的值。
// 假設(shè) this.state = { value: 0 } this.setState({ value: 1 }); console.log(this.state.value); // 0
React 也會嘗試將多次setState調(diào)用組合或者批處理為一次調(diào)用:
// 假設(shè) this.state = { value: 0 }; this.setState({ value: this.state.value + 1}); this.setState({ value: this.state.value + 1}); this.setState({ value: this.state.value + 1});
在上面所有的調(diào)用完成后,this.state.value將是1,而不是我們的期望值3。那么怎么得到期望值3呢?
setState接受一個函數(shù)作為它的參數(shù)
如果你傳遞一個函數(shù)作為setState的第一個參數(shù),React將會使用在當(dāng)前調(diào)用時刻的state去調(diào)用它并期望你返回一個對象合并到state中。所以你可以把我們上面的代碼改成下面這樣即可:
// 假設(shè) this.state = { value: 0 }; this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1}));
這樣this.state.value 的值就是 3了,就和上面我們認(rèn)為期望值應(yīng)該是3相一致了。
記住當(dāng)在更新state為一個值的時候應(yīng)始終使用這種語法,它的計算是基于前面的一個狀態(tài)的。
setState是同步的嗎???
記住你剛才學(xué)習(xí)到setState是異步的。事實證明并非始終如此。這取決于執(zhí)行上下文,請看下面的例子:
render() { return } inc() { console.log("before: " + this.state.test); this.setState({ test: this.state.test+1 }); console.log("after: " + this.state.test); }
點擊按鈕元素將會導(dǎo)致你的console中顯示:
// click! before: 1 after: 1 // click! before: 2 after: 2
但如果我們添加以下代碼:
componentDidMount() { setInterval(this.inc, 1000); }
我們將在console中看到:
before: 1 after: 2 before: 2 after: 3
因此,我們需要學(xué)習(xí)什么時候期望得到哪種行為嗎?并不是如此。假設(shè)setState的確是異步是非常安全的,因為在未來它就是如此。
setState接受一個回調(diào)函數(shù)
如果你需要執(zhí)行一些函數(shù),或者驗證狀態(tài)是否真的有更新正確。你還可以給setState傳遞一個函數(shù)作為第二個參數(shù),這個函數(shù)會在狀態(tài)更新完畢后得到執(zhí)行。請記住由于單個塊內(nèi)的所有更新會被合并成一個,這將導(dǎo)致每個setState中的回調(diào)中得到的state值是全更新的state。
另外一種可以保證你的代碼執(zhí)行是在更新完成以后的方式是將執(zhí)行代碼放在componentWillUpdate?或者?componentDidUpdate中。然而對比回調(diào)函數(shù)的方式,這兩個方法會在shouldComponentUpdate中阻止你的組件更新時不會被調(diào)用。
常見錯誤
其中最常見的錯誤之一就是在構(gòu)造函數(shù)中使用props設(shè)置state的值。考慮如下代碼:
class Component extends React.Component { constructor(props) { super(props); this.state = { value: this.props.value }; } render() { returnThe value is: {this.state.value}} }
如果它的父組件這樣render它:
它將會正確渲染value為42,但如果父組件中修改成如下:
那它仍會認(rèn)為this.state.value是42,這是因為React并不會銷毀組件并重新創(chuàng)建它——它會重用一旦渲染好的組件,并且不會重新執(zhí)行構(gòu)造函數(shù)。要避免這個問題,你應(yīng)該不要將props賦值給state,而應(yīng)在render方法中使用this.props.value。
如果你還是想要使用state(如果你的props是以一種非常復(fù)雜的計算的使用模式,你不希望每一次render都執(zhí)行這些復(fù)雜的計算),你還可以實現(xiàn)一種在需要的時候才去更新state的解決方案,例如:
class Component extends React.Component { constructor(props) { super(props); this.state = { value: this.props.value }; } componentWillReceiveProps(nextProps) { if(nextProps.value !== this.props.value) { this.setState({value: nextProps.value}); } } render() { returnThe value is: {this.state.value}} }
請記住任何componentWill*函數(shù)都不是一個合適的地方去觸發(fā)side effect(如ajax請求),所以請使用
componentDidUpdate(previousProps, previousState),同樣也提供和上面類似的if防護語句確保在沒有變化時不會執(zhí)行相關(guān)代碼。
寫在最后的話:這篇文章在Medium中獲得超過2.1K的贊,挺不錯的,值得翻譯!
翻譯如有不正,歡迎留言指出!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96064.html
摘要:原文地址由于只涉及層的處理,所以構(gòu)建大型應(yīng)用應(yīng)該搭配一個框架模式才能使后期維護成本相對較小正是官方給出的應(yīng)用架構(gòu),他推崇一種單向的數(shù)據(jù)流動模式,看下圖感受下整個流程是用戶與層交互,觸發(fā)使用進行分發(fā)觸發(fā)回調(diào)進行更新更新觸發(fā)層事件層收到信號進 原文地址:https://gmiam.com/post/react-... 由于 React 只涉及 UI 層的處理,所以構(gòu)建大型應(yīng)用應(yīng)該搭配一個框...
摘要:一般這種情況會在類的構(gòu)造函數(shù)內(nèi)創(chuàng)建一個屬性,引用或詞法域的,但后面會看到我們有更好的辦法,避免這種手工代碼。 換句話說,StateUp模式把面向?qū)ο蟮脑O(shè)計方法應(yīng)用到了狀態(tài)對象的管理上,在遵循React的組件化機制和基于props實現(xiàn)組件通訊方式的前提之下做到了這一點。 ---- 少婦白潔 閱讀本文之前,請確定你讀過React的官方文檔中關(guān)于Lifting State Up的論述: ht...
摘要:第一次了解這項特性的時候,真的有一種豁然開朗,發(fā)現(xiàn)新大陸的感覺。為了解決這一痛點,才會有剪頭函數(shù)的綁定特性。它同時具備和三個生命周期函數(shù)的執(zhí)行時機。 歡迎關(guān)注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 React Hooks 是從 v16.8 引入的又一開創(chuàng)性的新特性。第一次了解這項特性...
摘要:本文翻譯自原作者如果有任何版權(quán)問題,請聯(lián)系當(dāng)你在組件中調(diào)用時,你覺得會發(fā)生什么當(dāng)然,會用這條狀態(tài)重新渲染組件并且更新匹配到的,然后返回元素。如果你之前使用過一些渲染器比如說,你可能知道在頁面中使用超過一個渲染器是沒什么問題的。 本文翻譯自:How Does setState Know What to Do?原作者:Dan Abramov 如果有任何版權(quán)問題,請聯(lián)系shuirong199...
摘要:右側(cè)展現(xiàn)對應(yīng)產(chǎn)品。我們使用命名為的對象表示過濾條件信息,如下此數(shù)據(jù)需要在組件中進行維護。因為組件的子組件和都將依賴這項數(shù)據(jù)狀態(tài)。化應(yīng)用再回到之前的場景,我們設(shè)計化函數(shù),進一步可以簡化為對于的偏應(yīng)用即上面提到的相信大家已經(jīng)理解了這么做的好處。 showImg(https://segmentfault.com/img/remote/1460000014458612?w=1240&h=663...
閱讀 2109·2023-04-26 00:50
閱讀 2479·2021-10-13 09:39
閱讀 2201·2021-09-22 15:34
閱讀 1605·2021-09-04 16:41
閱讀 1336·2019-08-30 15:55
閱讀 2433·2019-08-30 15:53
閱讀 1707·2019-08-30 15:52
閱讀 748·2019-08-29 16:19