自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

React中setState同步更新策略

開(kāi)發(fā) 開(kāi)發(fā)工具
我們?cè)谏衔闹刑峒?,為了提高性能React將setState設(shè)置為批次更新,即是異步操作函數(shù),并不能以順序控制流的方式設(shè)置某些事件,我們也不能依賴(lài)于this.state來(lái)計(jì)算未來(lái)狀態(tài)。

setState 同步更新

我們?cè)谏衔闹刑峒?,為了提高性能React將setState設(shè)置為批次更新,即是異步操作函數(shù),并不能以順序控制流的方式設(shè)置某些事件,我們也不能依賴(lài)于this.state來(lái)計(jì)算未來(lái)狀態(tài)。典型的譬如我們希望在從服務(wù)端抓取數(shù)據(jù)并且渲染到界面之后,再隱藏加載進(jìn)度條或者外部加載提示:

  1. componentDidMount() { 
  2.     fetch('https://example.com'
  3.         .then((res) => res.json()) 
  4.         .then
  5.             (something) => { 
  6.                 this.setState({ something }); 
  7.                 StatusBar.setNetworkActivityIndicatorVisible(false); 
  8.             } 
  9.         ); 

因?yàn)閟etState函數(shù)并不會(huì)阻塞等待狀態(tài)更新完畢,因此setNetworkActivityIndicatorVisible有可能先于數(shù)據(jù)渲染完畢就執(zhí)行。我們可以選擇在componentWillUpdate與componentDidUpdate這兩個(gè)生命周期的回調(diào)函數(shù)中執(zhí)行setNetworkActivityIndicatorVisible,但是會(huì)讓代碼變得破碎,可讀性也不好。實(shí)際上在項(xiàng)目開(kāi)發(fā)中我們更頻繁遇見(jiàn)此類(lèi)問(wèn)題的場(chǎng)景是以某個(gè)變量控制元素可見(jiàn)性:

  1. this.setState({showForm : !this.state.showForm}); 

我們預(yù)期的效果是每次事件觸發(fā)后改變表單的可見(jiàn)性,但是在大型應(yīng)用程序中如果事件的觸發(fā)速度快于setState的更新速度,那么我們的值計(jì)算完全就是錯(cuò)的。本節(jié)就是討論兩種方式來(lái)保證setState的同步更新。

完成回調(diào)

setState函數(shù)的第二個(gè)參數(shù)允許傳入回調(diào)函數(shù),在狀態(tài)更新完畢后進(jìn)行調(diào)用,譬如:

  1. this.setState({ 
  2.      load: !this.state.load
  3.      count: this.state.count + 1 
  4.    }, () => { 
  5.      console.log(this.state.count); 
  6.      console.log('加載完成'
  7.    }); 

這里的回調(diào)函數(shù)用法相信大家很熟悉,就是JavaScript異步編程相關(guān)知識(shí),我們可以引入Promise來(lái)封裝setState:

  1. setStateAsync(state) { 
  2.     return new Promise((resolve) => { 
  3.       this.setState(state, resolve) 
  4.     }); 
  5.   } 

setStateAsync 返回的是Promise對(duì)象,在調(diào)用時(shí)我們可以使用Async/Await語(yǔ)法來(lái)優(yōu)化代碼風(fēng)格:

  1. async componentDidMount() { 
  2.    StatusBar.setNetworkActivityIndicatorVisible(true
  3.    const res = await fetch('https://api.ipify.org?format=json'
  4.    const {ip} = await res.json() 
  5.    await this.setStateAsync({ipAddress: ip}) 
  6.    StatusBar.setNetworkActivityIndicatorVisible(false
  7.  } 

這里我們就可以保證在setState渲染完畢之后調(diào)用外部狀態(tài)欄將網(wǎng)絡(luò)請(qǐng)求狀態(tài)修改為已結(jié)束,整個(gè)組件的完整定義為:

  1. class AwesomeProject extends Component { 
  2.   state = {} 
  3.   setStateAsync(state) { 
  4.     ... 
  5.   } 
  6.   async componentDidMount() { 
  7.    ... 
  8.   } 
  9.   render() { 
  10.     return ( 
  11.       <View style={styles.container}> 
  12.         <Text style={styles.welcome}> 
  13.           My IP is {this.state.ipAddress || 'Unknown'
  14.         </Text> 
  15.       </View
  16.     ); 
  17.   } 

傳入狀態(tài)計(jì)算函數(shù)

除了使用回調(diào)函數(shù)的方式監(jiān)聽(tīng)狀態(tài)更新結(jié)果之外,React還允許我們傳入某個(gè)狀態(tài)計(jì)算函數(shù)而不是對(duì)象來(lái)作為***個(gè)參數(shù)。狀態(tài)計(jì)算函數(shù)能夠?yàn)槲覀兲峁┛尚刨?lài)的組件的State與Props值,即會(huì)自動(dòng)地將我們的狀態(tài)更新操作添加到隊(duì)列中并等待前面的更新完畢后傳入***的狀態(tài)值:

  1. this.setState(function(prevState, props){  
  2. return {showForm: !prevState.showForm}  
  3. }); 

這里我們以簡(jiǎn)單的計(jì)數(shù)器為例,我們希望用戶(hù)點(diǎn)擊按鈕之后將計(jì)數(shù)值連加兩次,基本的組件為:

  1. class Counter extends React.Component{ 
  2.   constructor(props){ 
  3.     super(props); 
  4.     this.state = {count : 0}  
  5.     this.incrementCount = this.incrementCount.bind(this) 
  6.   } 
  7.   incrementCount(){ 
  8.     ... 
  9.   } 
  10.   render(){ 
  11.     return <div> 
  12.               <button onClick={this.incrementCount}>Increment</button> 
  13.               <div>{this.state.count}</div> 
  14.           </div> 
  15.   } 

直觀的寫(xiě)法我們可以連續(xù)調(diào)用兩次setState函數(shù),這邊的用法可能看起來(lái)有點(diǎn)怪異,不過(guò)更多的是為了說(shuō)明異步更新帶來(lái)的數(shù)據(jù)不可預(yù)測(cè)問(wèn)題。

  1. incrementCount(){ 
  2.    this.setState({count : this.state.count + 1})  
  3.    this.setState({count : this.state.count + 1}) 
  4.  } 

上述代碼的效果是每次點(diǎn)擊之后計(jì)數(shù)值只會(huì)加1,實(shí)際上第二個(gè)setState并沒(méi)有等待***個(gè)setState執(zhí)行完畢就開(kāi)始執(zhí)行了,因此其依賴(lài)的當(dāng)前計(jì)數(shù)值完全是錯(cuò)的。我們當(dāng)然可以使用上文提及的setStateAsync來(lái)進(jìn)行同步控制,不過(guò)這里我們使用狀態(tài)計(jì)算函數(shù)來(lái)保證同步性:

  1. incrementCount(){ 
  2.   this.setState((prevState, props) => ({ 
  3.      count: prevState.count + 1 
  4.    })); 
  5.   this.setState((prevState, props) => ({ 
  6.      count: prevState.count + 1 
  7.    })); 
  8.  } 

這里的第二個(gè)setState傳入的prevState值就是***個(gè)setState執(zhí)行完畢之后的計(jì)數(shù)值,也順利保證了連續(xù)自增兩次。

【本文是51CTO專(zhuān)欄作者“張梓雄 ”的原創(chuàng)文章,如需轉(zhuǎn)載請(qǐng)通過(guò)51CTO與作者聯(lián)系】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來(lái)源: 51CTO專(zhuān)欄
相關(guān)推薦

2022-06-13 06:20:42

setStatereact18

2011-11-04 14:07:20

微軟Hotmail策略

2020-02-10 09:35:18

數(shù)據(jù)中心服務(wù)器技術(shù)

2018-10-24 14:30:30

緩存服務(wù)更新

2024-12-03 10:59:36

2018-10-19 11:07:02

主流緩存更新

2024-05-10 08:12:12

React同步更新useState

2021-06-29 09:47:34

ReactSetState機(jī)制

2023-04-13 08:15:47

Redis緩存一致性

2012-02-01 10:29:13

2021-08-03 07:40:47

宏任務(wù)微任務(wù)React

2009-10-30 09:19:43

2009-03-09 18:46:11

Windows phoWindows Mob

2018-06-21 11:27:06

Windows 7更新停止

2022-01-25 00:08:08

Windows 10Windows 11微軟

2010-11-11 14:36:17

MySQL

2015-10-30 09:33:48

ChromeAndroid合一

2017-02-21 12:04:30

光纖FTTH寬帶網(wǎng)絡(luò)

2012-11-21 09:34:58

SaaS應(yīng)用SaaS應(yīng)用集成軟件集成

2009-03-10 14:00:18

網(wǎng)絡(luò)招聘
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)