摘要:簡單的舉下例子如等生命周期以及的事件即為異步更新,這里不顯示具體代碼。因為只有當父組件后才傳給子組件,那么如果要變成同步的,就需要放棄。
前言
在看React的官方文檔的時候, 發現了這么一句話,State Updates May Be Asynchronous,于是查詢了一波資料, 最后歸納成以下3個問題
setState為什么要異步更新,它是怎么做的?
setState什么時候會異步更新, 什么時候會同步更新?
既然setState需要異步更新, 為什么不讓用戶可以同步讀到state的新值,但更新仍然是異步?
常見場景下的異步更新以下是官方文檔的一個例子, 調用了3次incrementCount方法, 期望this.state.count的值是3, 但最后卻是1
incrementCount() { this.setState({count: this.state.count + 1}); } handleSomething() { // Let"s say `this.state.count` starts at 0. this.incrementCount(); this.incrementCount(); this.incrementCount(); // When React re-renders the component, `this.state.count` will be 1, but you expected 3. // This is because `incrementCount()` function above reads from `this.state.count`, // but React doesn"t update `this.state.count` until the component is re-rendered. // So `incrementCount()` ends up reading `this.state.count` as 0 every time, and sets it to 1. // The fix is described below! }
那么就可以引出第一個問題
setState為什么要異步更新,它是怎么做的?深入源碼你會發現:(引用程墨老師的setState何時同步更新狀態)
在 React 的 setState 函數實現中,會根據一個變量 isBatchingUpdates 判斷是直接更新 this.state 還是放到隊列中回頭再說,
而 isBatchingUpdates 默認是 false,也就表示 setState 會同步更新 this.state,
但是,有一個函數 batchedUpdates,這個函數會把 isBatchingUpdates 修改為 true,
而當 React 在調用事件處理函數之前就會調用這個 batchedUpdates,造成的后果,就是由 React 控制的事件處理過程 setState 不會同步更新 this.state。
然后我在網上引用了這張圖(侵刪)
從結論和圖都可以得出, setState是一個batching的過程, React官方認為, setState會導致re-rederning, 而re-rederning的代價是昂貴的, 所以他們會盡可能的把多次操作合并成一次提交。以下這段話是Dan在Issue中的回答:
中心意思大概就是:
同步更新setState并re-rendering的話在大部分情況下是無益的, 采用batching會有利于性能的提升, 例如當我們在瀏覽器插入一個點擊事件時,父子組件都調用了setState,在batching的情況下, 我們就不需要re-render兩次孩子組件,并且在退出事件之前re-render一次即可。
那么如果我們想立即讀取state的值, 其實還有一個方法, 如下代碼:
因為當傳入的是一個函數時,state讀取的是pending隊列中state的值
incrementCount() { this.setState((state) => { // Important: read `state` instead of `this.state` when updating. return {count: state.count + 1} }); } handleSomething() { // Let"s say `this.state.count` starts at 0. this.incrementCount(); this.incrementCount(); this.incrementCount(); // If you read `this.state.count` now, it would still be 0. // But when React re-renders the component, it will be 3. }
當然, 仔細看React文檔的話, 可以發現, State Updates May Be Asynchronou里面有一個may的字眼,也就是可能是異步更新, 因而引出第二個問題
setState什么時候會異步更新, 什么時候會同步更新?其實從第一個問題中我們就知道,React是根據isBatchingUpdates來合并更新的, 那么當調用setState的方法或者函數不是由React控制的話, setState自然就是同步更新了。
簡單的舉下例子:
如componentDidMount等生命周期以及React的事件即為異步更新,這里不顯示具體代碼。
如自定義的瀏覽器事件,setTimeout,setInterval等脫離React控制的方法, 即為同步更新, 如下(引用程墨老師的setState何時同步更新狀態)
componentDidMount() { document.querySelector("#btn-raw").addEventListener("click", this.onClick); } onClick() { this.setState({count: this.state.count + 1}); console.log("# this.state", this.state); } // ...... render() { console.log("#enter render"); return () }{this.state.count}
有的人也會想能不能React依然合并更新, 但用戶可以同步讀取this.state的值, 這個問題在React的一個Issue上有提到, 也是我們的第三個問題
既然setState需要異步更新, 為什么不讓用戶可以同步讀到state的新值,但更新仍然是異步?這個問題可以直接在Dan的回答中得到:
This is because, in the model you proposed, this.state would be flushed immediately but this.props wouldn’t.
And we can’t immediately flush this.props without re-rendering the parent, which means we would have to give up on batching (which, depending on the case, can degrade the performance very significantly).
大概意思就是說:
如果在應用中,this.state的值是同步,但是this.props卻不是同步的。因為props只有當re-rendering父組件后才傳給子組件,那么如果要props變成同步的, 就需要放棄batching。 但是batching不能放棄。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101595.html
摘要:布局如下對于這塊,我不是很理解,后發現,注銷這個樣式,用可以解決。后查閱一些資料,到了原因。 -12.24-:html布局如下: html css javascript vue css: tab{ width: 600px; margin: 0 auto; } .tab-tit{ width: 600px; font-si...
摘要:三種的區別即對應中的值,如,服務器對任務都返回同一個,具體的路徑由瀏覽器區分,因為瀏覽器不會發送后面的值給服務器。如果是即變成這樣,,所以要對服務器配置不同的返回不同的資源。就是沒有的情況,比如。 三種Router的區別 1. HashRouter: 即對應url中的hash值,如xx.com/#/a、xx.com/#/a/b, 服務器對任務url都返回同一個url,具體的路徑由瀏覽器...
摘要:簡介是一種搭建客戶端的應用架構,更像是一種模式而不是一個框架。 簡介 Flux是一種搭建WEB客戶端的應用架構,更像是一種模式而不是一個框架。 特點 單向數據流 showImg(https://segmentfault.com/img/remote/1460000018128072?w=1300&h=708); 與MVC的比較 1.傳統的MVC如下所示(是一個雙向數...
摘要:基礎簡單基礎數據類型值得注意的是的值是,表示一個空對象指針,沒有指向任何對象。的值是,表示申明變量或對象的屬性卻未初始化。值是派生自的,所以對他們執行相等測試會返回。字符串單引號和雙引號都可以用來表示字符串,只要前后一致即可。 目的 記憶總是會隨著時間而淡化,學習了點什么,就記錄下點什么。 做點什么,總比不做要好。 基礎 簡單(基礎)數據類型 Number ...
摘要:修改菜單首先,修改,為什么看了就明白了提示信息在里修改最后大多數要修改的內容都在里,希望可以幫助到你,沒涉及的那你就再百度一下吧,學藝不精歡迎指正 1.修改菜單首先,修改dede/temples/index2.html + dede/inc/inc_menu.php,為什么?!看了就明白了 2.dede提示信息在dede/sys_data_done.php 里修改 最后大多數要修改的...
閱讀 2623·2021-11-18 10:07
閱讀 1083·2021-08-03 14:04
閱讀 726·2019-08-30 13:08
閱讀 2578·2019-08-29 15:33
閱讀 1086·2019-08-29 14:07
閱讀 2985·2019-08-29 14:04
閱讀 1435·2019-08-29 11:19
閱讀 1143·2019-08-29 10:59