99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

React中setState同步更新策略

發(fā)布時(shí)間:2017-01-09 23:09  回復(fù):0  查看:2543   最后回復(fù):2017-01-09 23:09  

本文和大家分享的主要是ReactsetState同步更新相關(guān)內(nèi)容,希望對(duì)大家學(xué)習(xí)React有所幫助。

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

  componentDidMount() {

  fetch('https://example.com')

  .then((res) => res.json())

  .then(

  (something) => {

  this.setState({ something });

  StatusBar.setNetworkActivityIndicatorVisible(false);

  }

  );

  }

  因?yàn)?/span> setState 函數(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)此類問(wèn)題的場(chǎng)景是以某個(gè)變量控制元素可見(jiàn)性:

  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)用,譬如:

  this.setState({

  load: !this.state.load,

  count: this.state.count + 1

  }, () => {

  console.log(this.state.count);

  console.log('加載完成')

  });

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

  setStateAsync(state) {

  return new Promise((resolve) => {

  this.setState(state, resolve)

  });

  }

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

  async componentDidMount() {

  StatusBar.setNetworkActivityIndicatorVisible(true)

  const res = await fetch('https://api.ipify.org?format=json')

  const {ip} = await res.json()

  await this.setStateAsync({ipAddress: ip})

  StatusBar.setNetworkActivityIndicatorVisible(false)

  }

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

  class AwesomeProject extends Component {

  state = {}

  setStateAsync(state) {

  ...

  }

  async componentDidMount() {

  ...

  }

  render() {

  return (

  

  

  My IP is {this.state.ipAddress || 'Unknown'}

  

  

  );

  }

  }

  該組件的執(zhí)行效果如下所示:

React中setState同步更新策略

傳入狀態(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)槲覀兲峁┛尚刨嚨慕M件的StateProps值,即會(huì)自動(dòng)地將我們的狀態(tài)更新操作添加到隊(duì)列中并等待前面的更新完畢后傳入最新的狀態(tài)值:

  this.setState(function(prevState, props){

  return {showForm: !prevState.showForm}

  });

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

  class Counter extends React.Component{

  constructor(props){

  super(props);

  this.state = {count : 0}

  this.incrementCount = this.incrementCount.bind(this)

  }

  incrementCount(){

  ...

  }

  render(){

  return 

  <button onClick={this.incrementCount}>Increment

  

{this.state.count}

  

  }

  }

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

  incrementCount(){

  this.setState({count : this.state.count + 1})

  this.setState({count : this.state.count + 1})

  }

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

  incrementCount(){

  this.setState((prevState, props) => ({

  count: prevState.count + 1

  }));

  this.setState((prevState, props) => ({

  count: prevState.count + 1

  }));

  }

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

 

來(lái)源:某熊的全棧之路

 

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?