成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

關(guān)于this.setState( )中的數(shù)據(jù)延遲問題

Lorry_Lu / 3242人閱讀

摘要:判斷當前是否處于批量更新狀態(tài),如果是,將當前組件加入待更新的組件隊列中。將組件的暫存隊列中的進行合并,獲得最終要更新的對象,并將隊列置為空。執(zhí)行生命周期,根據(jù)返回值判斷是否要繼續(xù)更新。

this.setState( )方法是React.js中最常見的一種方法,利用它可以控制各種狀態(tài)變化,達到頁面各種交互效果,但是,我們在React開發(fā)中偶爾會發(fā)現(xiàn),明明已經(jīng)通過this.setState( )方法處理過某個state的值,但是在后續(xù)的方法里,log打印出來仍然是之前的值,或者,第一次獲取到原來的值,第二次才能獲取到設置之后的新值,讓人誤以為是因為電腦或瀏覽器性能問題造成的"延遲"問題。

執(zhí)行過程

為了理解這個問題,我們首先來看一下setState這個過程中發(fā)生了什么:

setState傳入的partialState參數(shù)存儲在當前組件實例的state暫存隊列中。

判斷當前React是否處于批量更新狀態(tài),如果是,將當前組件加入待更新的組件隊列中。

如果未處于批量更新狀態(tài),將批量更新狀態(tài)標識設置為true,用事務再次調(diào)用前一步方法,保證當前組件加入到了待更新組件隊列中。

調(diào)用事務的waper方法,遍歷待更新組件隊列依次執(zhí)行更新。

執(zhí)行生命周期componentWillReceiveProps。

將組件的state暫存隊列中的state進行合并,獲得最終要更新的state對象,并將隊列置為空。

執(zhí)行生命周期componentShouldUpdate,根據(jù)返回值判斷是否要繼續(xù)更新。

執(zhí)行生命周期componentWillUpdate

執(zhí)行真正的更新,render重新渲染。

執(zhí)行生命周期componentDidUpdate。

官方解釋

首先思考為什么會出現(xiàn)這種情況,在facebook給出的官方文檔中我們可以看到這么一段話:

setState(updater[, callback])

Think of setState( ) as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.

setState( ) does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState( ) a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.

總結(jié)以下,就是以下幾點:

setState( ) 更類似于是一種請求而不是立即更新組件的命令

為了更好的性能,React會延遲調(diào)用它,不會保證state的變更會立即生效,而是會批量推遲更新

官方承認會存在隱患

建議在componentDidUpdate中執(zhí)行或利用回調(diào)函數(shù)(setState(updater, callback))

舉個簡單例子:

constructor(props) {
  super(props);
  this.state = {
    num: 1
  };
}

componentDidMount = () => {
  this.setState({ num: this.state.num + 1 });
  console.log(this.state.num);   // 1
}

這是因為this.setState( )本身是異步的,程序異步運行,可以提高程序運行的效率,不必等一個程序跑完,再跑下一個程序,特別當這兩個程序是無關(guān)的時候。React會去合并所有的state變化,在前一個方法未執(zhí)行完時,就先開始運行后一個方法。但是實際操作中,為了能實時獲取后一個狀態(tài)值,需要一些解決的辦法。

利用全局屬性

嘗試一下?lián)Q個寫法,利用全局屬性的辦法而不是用state的方式去獲取數(shù)據(jù):

constructor(props) {
  super(props);
  this.num = 1;
}

componentDidMount = () => {
  this.num = this.num + 1;
  console.log(this.num);   // 2
}

這其實是一種取巧的方式,寫法方便,原理簡單,但是并不十分推薦,因為它并不符合React中關(guān)于有狀態(tài)組件的設計理念,存在有可能無法觸發(fā)刷新的風險(雖然在我的開發(fā)過程從沒有發(fā)生這樣的事),所以還是希望大家優(yōu)先使用下面的方法。

利用回調(diào)函數(shù)

回調(diào)函數(shù)眾所周知,就是某個函數(shù)執(zhí)行完畢后執(zhí)行的函數(shù),利用它可以確保在this.setState( )整個函數(shù)執(zhí)行完成之后去獲取this.state.xxx的值:

constructor(props) {
  super(props);
  this.state = {
    num: 1
  };
}

componentDidMount = () => {
  this.setState({ num: this.state.num + 1 }, () => {
    console.log(this.state.num);   // 2
  });
  console.log(this.state.num);   // 1
}

控制臺按順序先后打印出兩個結(jié)果:

1
2
利用setTimeout( )

首先簡單回顧一下,利用setTimeout( )模擬一下前文提到的Javascript中的異步:

foo = () => {
  console.log("11111111");
  setTimeout(function(){
    console.log("22222222");
  },1000);
};
bar = () => {
  console.log("33333333");  
}
foo();
bar();
// 11111111
// 33333333
// 22222222

所以,在上述代碼塊中,在前一方法(foo)執(zhí)行時,后一方法(bar)也可以執(zhí)行。符合異步的基本概念,程序并不按順序執(zhí)行。在foo函數(shù)中執(zhí)行到setTimeout的時候,函數(shù)會跳出,并先執(zhí)行bar( )方法,這樣就模擬了一個異步的效果。這里順便再提一下前面說的,setState方法通過一個隊列機制實現(xiàn)state更新,當執(zhí)行setState的時候,會將需要更新的state合并之后放入狀態(tài)隊列,而不會立即更新,通過下面的例子可見。

constructor(props) {
  super(props);
  this.state = {
    num: 1,
  };
}
componentWillMount = () => {
  this.setState({
    num: this.state.num + 1,
  });
  console.log(this.state.num);
  this.setState({
    num: this.state.num + 1,
  });
  console.log(this.state.num);
}

render() {
  console.log(this.state.num);
  return (
); }

代碼輸出結(jié)果為 1,1,2

利用setTimeout方法可以解決state的異步問題,因為setState只在合成事件和鉤子函數(shù)中是“異步”的,在原生事件和setTimeout 中都是同步的:

componentWillMount = () => {
  setTimeout(() => {
    this.setState({
      num: this.state.num + 1,
    });
    console.log(this.state.num);  // 1
    this.setState({
      num: this.state.num + 1,
    });
    console.log(this.state.num);  // 2
  }, 0);
} 
利用componentDidUpdate( )

根據(jù)前面文檔所說,在componentDidUpdate( )方法中去獲取新的state值,根據(jù)React的生命周期,此時this.state已經(jīng)更新。

constructor(props) {
    super(props);
    this.state = {
      num: 1
    };
}

componentWillMount = () => {
    this.setState({ num: this.state.num + 1 });
}

componentDidUpdate = () => {
    console.log(this.state.num);   // 2
}
警告

??注意,很多新人在遇到這種問題時無所適從,可能會用一些投機取巧的方式,方面的全局對象是一種方式,還有一種就是繞過setState直接賦值:

this.state.num = 2   // 2

理論上講,這種方法當然也能達到賦值目的,但將state設計成更新延緩到最后批量合并再去渲染,對于應用的性能優(yōu)化是有極大好處的,如果每次的狀態(tài)改變都去重新渲染真實dom,那么它將帶來巨大的性能消耗,所以不建議上面寫法。

??如果在shouldComponentUpdate或者componentWillUpdate方法中調(diào)用setState,此時this._pending-StateQueue != null,就會造成循環(huán)調(diào)用,使得瀏覽器內(nèi)存占滿后崩潰。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/109957.html

相關(guān)文章

  • React 中 setState() 為什么是異步的?

    摘要:正文在回復中表示為什么是異步的,這并沒有一個明顯的答案,每種方案都有它的權(quán)衡。需要注意的是,異步更新是有可能實現(xiàn)這種設想的前提。 前言 不知道大家有沒有過這個疑問,React 中 setState() 為什么是異步的?我一度認為 setState() 是同步的,知道它是異步的之后很是困惑,甚至期待 React 能出一個 setStateSync() 之類的 API。同樣有此疑問的還有 ...

    anonymoussf 評論0 收藏0
  • 一個關(guān)于React.Component.setState問題

    摘要:不保證這個狀態(tài)的更新是立即執(zhí)行的。這個問題導致如果開發(fā)者在之后立即去訪問可能訪問的不是最新的狀態(tài)。不應該被直接更改,而是應該新建一個來表示更新后的狀態(tài)。實驗采用基于控制變量法的對照試驗。至于的問題,留給讀者自己吧。 React組件重新渲染的條件是: B.只要調(diào)用this.setState()就會發(fā)生重新渲染。 C.必須調(diào)用this.setState()且傳遞不同于當前this.setS...

    BoYang 評論0 收藏0
  • 用RxJS和react開發(fā)mac地址輸入框

    摘要:項目簡介本次使用了和開發(fā)了一個地址輸入框,主要實現(xiàn)的功能有限制輸入符合條件的字符并每隔兩位可以自動添加用于分割的冒號。項目屏蔽了的事件處理,同時使用來手動控制光標。繼承于和因此同時具有和兩者的方法。后面的和都是需要利用最新的來進行判斷的。 項目簡介 本次使用了RxJS和react開發(fā)了一個mac地址輸入框,主要實現(xiàn)的功能有限制輸入符合條件的字符1-9,a-f,并每隔兩位可以自動添加用于...

    CastlePeaK 評論0 收藏0
  • 從 0 到 1 實現(xiàn) React 系列 —— 4.優(yōu)化setState和ref的實現(xiàn)

    摘要:異步渲染利用事件循環(huán),延遲渲染函數(shù)的調(diào)用調(diào)用回調(diào)函數(shù)處理后跟函數(shù)的情況淺合并邏輯事件循環(huán),關(guān)于的事件循環(huán)和的事件循環(huán)后續(xù)會單獨寫篇文章。 showImg(https://segmentfault.com/img/remote/1460000015785464?w=640&h=280); 看源碼一個痛處是會陷進理不順主干的困局中,本系列文章在實現(xiàn)一個 (x)react 的同時理順 Rea...

    wangdai 評論0 收藏0
  • 如何優(yōu)雅地在React中處理事件響應

    摘要:處理事件響應是應用中非常重要的一部分。中,處理事件響應的方式有多種。關(guān)于事件響應的回調(diào)函數(shù),還有一個地方需要注意。不管你在回調(diào)函數(shù)中有沒有顯式的聲明事件參數(shù),都會把事件作為參數(shù)傳遞給回調(diào)函數(shù),且參數(shù)的位置總是在其他自定義參數(shù)的后面。 React中定義一個組件,可以通過React.createClass或者ES6的class。本文討論的React組件是基于class定義的組件。采用cla...

    buildupchao 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<