react同步請求_React中setState同步更新策略

setState 同步更新

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

componentDidMount() {

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

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

.then(

(something) => {

this.setState({ something });

StatusBar.setNetworkActivityIndicatorVisible(false);

}

);

}

因為setState函數并不會阻塞等待狀態更新完畢,因此setNetworkActivityIndicatorVisible有可能先于數據渲染完畢就執行。我們可以選擇在componentWillUpdate與componentDidUpdate這兩個生命周期的回調函數中執行setNetworkActivityIndicatorVisible,但是會讓代碼變得破碎,可讀性也不好。實際上在項目開發中我們更頻繁遇見此類問題的場景是以某個變量控制元素可見性:

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

我們預期的效果是每次事件觸發后改變表單的可見性,但是在大型應用程序中如果事件的觸發速度快于setState的更新速度,那么我們的值計算完全就是錯的。本節就是討論兩種方式來保證setState的同步更新。

完成回調

setState函數的第二個參數允許傳入回調函數,在狀態更新完畢后進行調用,譬如:

this.setState({

load: !this.state.load,

count: this.state.count + 1

}, () => {

console.log(this.state.count);

console.log('加載完成')

});

這里的回調函數用法相信大家很熟悉,就是JavaScript異步編程相關知識,我們可以引入Promise來封裝setState:

setStateAsync(state) {

return new Promise((resolve) => {

this.setState(state, resolve)

});

}

setStateAsync返回的是Promise對象,在調用時我們可以使用Async/Await語法來優化代碼風格:

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渲染完畢之后調用外部狀態欄將網絡請求狀態修改為已結束,整個組件的完整定義為:

class AwesomeProject extends Component {

state = {}

setStateAsync(state) {

...

}

async componentDidMount() {

...

}

render() {

return (

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

);

}

}

該組件的執行效果如下所示:

1460000008051631?w=750&h=1334

傳入狀態計算函數

除了使用回調函數的方式監聽狀態更新結果之外,React還允許我們傳入某個狀態計算函數而不是對象來作為第一個參數。狀態計算函數能夠為我們提供可信賴的組件的State與Props值,即會自動地將我們的狀態更新操作添加到隊列中并等待前面的更新完畢后傳入最新的狀態值:

this.setState(function(prevState, props){

return {showForm: !prevState.showForm}

});

這里我們以簡單的計數器為例,我們希望用戶點擊按鈕之后將計數值連加兩次,基本的組件為:

class Counter extends React.Component{

constructor(props){

super(props);

this.state = {count : 0}

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

}

incrementCount(){

...

}

render(){

return

Increment

{this.state.count}

}

}

直觀的寫法我們可以連續調用兩次setState函數,這邊的用法可能看起來有點怪異,不過更多的是為了說明異步更新帶來的數據不可預測問題。

incrementCount(){

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

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

}

上述代碼的效果是每次點擊之后計數值只會加1,實際上第二個setState并沒有等待第一個setState執行完畢就開始執行了,因此其依賴的當前計數值完全是錯的。我們當然可以使用上文提及的setStateAsync來進行同步控制,不過這里我們使用狀態計算函數來保證同步性:

incrementCount(){

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

count: prevState.count + 1

}));

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

count: prevState.count + 1

}));

}

這里的第二個setState傳入的prevState值就是第一個setState執行完畢之后的計數值,也順利保證了連續自增兩次。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533237.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533237.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533237.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DVWA設置mysql_dvwa安裝、配置、使用教程(Linux)

一、搭建LAMP環境二、安裝DVWA2.1 下載dvwa2.2 解壓安裝將下載的應用解壓到apache默認的主目錄/var/www/html:unzip DVWA-master.zip -d /usr/www/html2.3 啟用功能dvwa上的漏洞,需要些刻意的配置才能被利用。訪問:http://172.0.0.1/dvwa如下…

eclipse mysql jndi_Java開發網 - tomcat5配置jndi的問題 (jdbc:comp is not bound in this Context)...

Posted by:returnerPosted on:2004-11-09 22:42tomcat5配置jndi的問題;斑竹高手們來看看啊,情況緊急!!!!!!!!10萬分感謝這個問題我是搜索出來的,我也遇到了同…

java正則效率_善用Pattern提高你的應用處理正則表達式的效率(Java)

舉個簡單了例子,在一個需要用于注冊登錄的b/s模式的應用中,在瀏覽器驗證用戶注冊表單的合法性是必須的,但你為了防止hacker,在服務器再驗證一次肯定也是必須的。題目:在服務器端驗證郵箱是否合法:通常你可能…

java jwindow 鍵盤_各位老哥求救,JWINDOW無法接收到鍵盤監聽

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓下面po代碼啊。這是我的類。class DragWindow extends JWindow{int positionX;int positionY;public DragWindow() {try {jbInit();}catch(Exception e) {e.printStackTrace();}}private void jbInit() throws Exception {this.add…

java jdbc rowset_JAVA基礎知識之JDBC——RowSet

RowSet概念在C#中,提供了一個DataSet,可以把數據庫的數據放在內存中進行離線操作(讀寫),操作完成之后再同步到數據庫中去,Java中則提供了類似的功能RowSet.RowSet接口繼承自ResultSet接口。與ResultSet相比,RowSet默認…

java廚房_JAVA環境搭建,廚房安裝圖文教程!

在“系統變量”欄下執行三項操作:①新建“Java_Home”,設置其值為 JDK所在的絕對路徑,如果你的事剛才的默認路徑,那值為:C:Program FilesJavajdk1.7.0_02②新建“Classpath”(如果已有,則直接編輯)&#xf…

java post get 請求_java get post 請求

packagewzh.Http;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.URL;importjava.net.URLConnection;importjava.util.List;importjava.util.Map;public classHttpRequest {/*** 向指定UR…

用java做日記本系統_jsp+servlet開發java web個人日記本系統

項目描述Jsp_Servlet技術使用個人日記本系統,主要有日記分類,添加日記,刪除日記和一些個人資料的修改。運行環境jdk8tomcat7mysql5.6IntelliJ IDEA(eclipse)項目技術(必填)Jsp Servletbootstrapjqueryckeditor數據庫文件(可選)鏈接&#xff1…

java類加載過程_java類的加載過程

在這本書里面,在講到類初始化的五種情況時,提及了一個比較有趣的事情。先來看看下面的代碼public class SubClass {static{System.err.println("I m your son");}public static final int name 111;}這個時候如果調用SubClass.name&#xff0…

java mvc 導出excel_Java springMVC POI 導出 EXCEL

思路 :將需要導出的數據存放在一個List中創建一個EXCEL表 注意 XSSFWorkbook 只能操作2007以上的版本,XSSFWorkbook 只能操作2003一下的版本,所以需要的時候可以使用 Workbook創建對象處理兼容性遍歷List 并將每條數據 寫入 EXCEL表中具體代碼…

java 排序原理_簡單選擇排序算法原理及java實現(超詳細)

簡單選擇排序的原理簡單選擇排序的原理非常簡單,即在待排序的數列中尋找最大(或者最小)的一個數,與第 1 個元素進行交換,接著在剩余的待排序的數列中繼續找最大(最小)的一個數,與第 2 個元素交換。以此類推,一直到待排…

python對象點方法_python面向對象知識點疏理

面向對象技術簡介類:用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。class類變量:類變量在整個實例化的對象中是公用的。類變量定義在類中且在函數體之外。類變量通常不作為實例變量使用。數據成員&#…

ckeditor java 上傳_CKEditor粘貼圖片自動上傳到服務器(Java版)

環境:java,springmvc,ckeditor,tomcat,maven情況:在做項目的時候發現本地圖片粘貼到ckeditor中,img標簽的src中的值是“data:image/png;base64,”開頭的,后面會跟一串字符串,圖片越大字符串越長,這樣的圖片…

java 序列化聲明_顯式聲明默認Java類序列化方法的原因是什么?

我定期看到具有以下結構的Java類:class MyClass implements Serializable {private static final long serialVersionUID 1L;// ...private void writeObject(final java.io.ObjectOutputStream s) throws IOException {s.defaultWriteObject();}private void read…

java 百度poi_Android應用中使用百度地圖API之POI(三)

先看執行后的圖吧:POI(Point of Interest)。中文能夠翻譯為“興趣點”。在地理信息系統中。一個POI能夠是一棟房子、一個商鋪、一個郵筒、一個公交站等 具體:http://developer.baidu.com/map/sdkandev-4.htm主要應用 MKSearch 類:com.baidu.…

java 順序存儲鍵值對_java://Comparator、Comparable的用法(按照要求將map集合的鍵值對進行順序輸出)...

import java.util.*;public class Person implements Comparable//使Person的屬性具有比較性{private String name;private int age;public Person(String name,int age)//初始化構造函數{this.name name;this.age age;}public void set(String name,int age)//重新設置姓名和…

java日歷事件處理_日歷表的事件處理和管理(劉靜)

1 //添加gridview,顯示具體的日期2 SuppressLint("ResourceAsColor")3 private voidaddGridView() {4 LinearLayout.LayoutParams params newLinearLayout.LayoutParams(5 LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);6 //取得屏幕的寬度和高度7 WindowMa…

java第四次上機作業_第十java上機作業

第十java上機作業 第七章上級作業 7.1 public class Rectangle { double width1; double height1; String color“white“; public Rectangle(){} public Rectangle(double width,double height,String color) { this.widthwidth; this.heightheight; this.colorcolor; } publi…

java解析帶斜杠的參數_Java Spring MVC應用程序僅接受帶有斜杠的POST請求

war文件名是forms.war。 web.xml中的url模式為"/"控制器操作的RequestMapping為"/"如果遇到localhost:8080 /表單,則RequestMethod.GET操作正常工作如果針對localhost:8080/forms點擊發布數據,則不會觸發RequestMethod.P…

java文件編碼格式環境變量_Jenkins maven 構建亂碼,修改file.encoding系統變量編碼為UTF-8...

一切都是windows的控制臺默認編碼GBK問題情景:使用jenkins構建,console 輸出的中文亂碼。代碼編碼格式是utf-8,因為Jenkins會默認讀取當前系統的編碼格式,導致構建日志亂碼和selenium自動化測試輸入的中文亂碼。控制臺輸出亂碼摸索…