成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

悄悄告訴你:React18文檔里寫錯的地方

開發 前端
React作為一款維護了快10年的框架,在經歷重大版本更新后要保持框架行為前后一致,實屬不易。

大家好,我卡頌

React18正式版已經發布一段時間了,如果你升級到v18,且仍使用ReactDOM.render創建應用,會收到如下報警:

大意是說:v18使用createRoot而不是render創建應用,如果你仍使用render創建應用,那么應用的行為將同v17一樣。

React團隊之所以有底氣讓大家都升級到v18,使用createRoot,是因為他們作出了承諾:

大意是說:如果你升級到v18,只要不使用「并發特性」(比如useTransition),React會和之前版本表現一致(更新會同步、不可中斷)。

今天這篇文章想說的是:某些情況下,上述說法是錯誤的。

不說廢話,上示例示

例中有a、b兩個狀態,首次渲染完2秒后會觸發a、b更新。

其中觸發b更新的方式比較特殊:模擬點擊,間接觸發b更新:

function App() {
const [a, setA] = useState(0);
const [b, setB] = useState(0);
const BtnRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
setTimeout(() => {
setA(9000);
BtnRef.current?.click();
}, 2000);
}, []);
return (
<div>
<button
ref={BtnRef}
onClick={() => setB(1)}>
b: {b}
</button>
{Array(a).fill(0).map((_, i) => {
return <div key={i}>{a}</div>;
})}
</div>
);
}

完整示例地址[1]

現在我們有兩種掛載的方式。

v18之前的方式:

const rootElement = document.getElementById("root");
// v18之前創建應用的方式
ReactDOM.render(<App/>, rootElement);

v18提供的方式:

const root = ReactDOM.createRoot(rootElement);
// v18創建應用的方式
root.render(
<App />
);

為了看清這兩者的區別,有兩種方式:

調大setA(9000)中的值,使頁面渲染更多項。頁面渲染時卡頓越明顯,渲染順序的差異越明顯。

setTimeout(() => {
setA(9000);
BtnRef.current?.click();
}, 2000);

在react-dom.development.js的commitRootImpl方法中打斷點。

這個方法是React渲染時調用的方法,在這里打斷點可以看出頁面渲染的順序。

對于ReactDOM.render創建的應用,觸發更新后渲染順序如下:

首先:

其次:

對于ReactDOM.createRoot創建的應用,觸發更新后渲染順序如下:

首先:

其次:

渲染順序顯然是變了,這和React文檔里的說法是相悖的。

背后的原因是什么呢?

更新的優先級,無處不在

先解釋下示例中的b為什么采用「觸發onClick事件」的方式間接觸發更新:

BtnRef.current?.click();

這是因為:不同方式觸發的更新有不同「優先級」,onClick回調中觸發的更新是最高優的,即「同步優先級」。

那么問題來了,v18不使用并發特性,所有更新不都該是「同步、不可中斷」么?

這話是沒錯,更新本身是「同步、不可中斷」的。但是更新是需要調度的。

在示例中,如果采用ReactDOM.createRoot創建應用,那么觸發更新時的優先級如下:

setTimeout(() => {
// 觸發更新,優先級為“默認優先級”
setA(9000);
// 觸發更新,優先級為“同步優先級”
BtnRef.current?.click();
}, 2000);

接下來React的執行流程如下:

  1. a觸發更新,優先級為“默認優先級”。
  2. 調度a的更新,優先級為“默認優先級”。
  3. b觸發更新,優先級為“同步優先級”。
  4. 調度b的更新,優先級為“同步優先級”。
  5. 此時發現已經有個更新在調度(a的更新),且優先級更低(默認優先級 < 同步優先級)。
  6. 取消a的更新的調度,轉而開始調度b的更新。
  7. 調度流程結束,開始同步、不可中斷的執行b的更新。
  8. b對應更新渲染到頁面中。
  9. 此時發現還有一個更新(a的更新),調度他。
  10. 調度流程結束,開始同步、不可中斷的執行a的更新。
  11. a對應更新渲染到頁面中。

可見,只要采用ReactDOM.createRoot創建應用,那么「優先級」的影響就會一直存在,與「使用了并發特性」的區別是:

  • 只有「默認優先級」與「同步優先級」。
  • 優先級只會影響調度,不會中斷更新的執行。

老版React的歷史包袱

那么采用ReactDOM.render創建的應用執行順序又是怎么一回事呢?

記不記得一道經典(且毫無意義)的React面試題:React的更新是同步還是異步的?

下面兩種情況,a打印的結果是1么?

// 情況1
onClick() {
this.setState({a: 1});
console.log(a);
}
// 情況2
onClick() {
setTimeout(() => {
this.setState({a: 1});
console.log(a);
})
}

其中,情況2中a打印結果是1。

之所以會有這種情況,是React早期實現批處理時的瑕疵造成的,并不是什么有意為之的特性。

當React使用Fiber架構重構后,完全可以規避這個瑕疵。但為了與老版本行為保持一致,刻意實現成這樣。

所以,在我們的示例中,這兩個更新不會受到「優先級」的影響,但會受到「為了兼容老版本」造成的影響:

setTimeout(() => {
setA(9000);
BtnRef.current?.click();
}, 2000);

React的執行流程如下:

  1. a觸發更新,因為是在setTimeout中觸發的,所以會同步執行后續更新流程。
  2. a對應更新渲染到頁面中。
  3. b觸發更新,因為是在setTimeout中觸發的,所以會同步執行后續更新流程。
  4. b對應更新渲染到頁面中。

總結

React作為一款維護了快10年的框架,在經歷重大版本更新后要保持框架行為前后一致,實屬不易。

更新順序的變化對一般應用影響不大。

但是,如果你的應用依賴更新后「頁面中當前的值」作出后續判斷,那么需要注意升級到v18后的這些細微變化。

參考資料

[1]完整示例地址:

https://codesandbox.io/s/strange-cartwright-iq1s2m?file=/src/index.tsx。

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2022-03-16 17:01:35

React18并發的React組件render

2021-06-16 06:05:25

React18React

2020-06-16 09:55:52

數據庫MySQL技術

2021-11-01 19:49:55

React組件模式

2020-04-30 11:11:30

MySQLMGR數據庫

2021-06-22 07:45:57

React18startTransiReact

2020-12-30 09:18:46

JVM內部信息

2023-03-21 08:31:13

ReconcilerFiber架構

2015-02-11 09:37:14

2021-06-22 07:30:07

React18Automatic b自動批處理

2022-03-30 14:22:55

ReactReact18并發特性

2016-06-27 16:29:04

戴爾閃存

2015-06-25 17:28:44

免費代理網絡安全

2023-03-28 07:59:57

ReactReconciler

2021-11-29 06:05:31

React組件前端

2022-03-25 08:31:09

ReactReact 18升級

2022-04-26 06:43:12

文檔TCPLinux

2021-11-30 05:45:48

React組件前端

2018-08-27 14:44:42

文檔云

2022-07-03 20:53:23

React18請求數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品久久久久久久久久久 | 亚洲精品福利在线 | 日韩成人在线视频 | 精品美女视频在线观看免费软件 | 欧美一级做a爰片免费视频 国产美女特级嫩嫩嫩bbb片 | www.亚洲区| 午夜精品久久久久久久久久久久久 | 一区二区日韩 | 91观看 | 自拍偷拍第一页 | 国产在线一区观看 | 91精品一区二区三区久久久久 | 99免费精品视频 | 欧美日韩国产高清 | 黑人精品欧美一区二区蜜桃 | 久久久久国产 | 五月婷婷色 | 91一区二区三区 | 国产成人综合在线 | 影视先锋av资源噜噜 | 精产国产伦理一二三区 | 日韩成人精品一区 | 午夜寂寞影院列表 | 日韩α片| 国产资源视频 | 国产网站久久 | 免费一区 | 日本高清不卡视频 | 日本五月婷婷 | 天堂免费看片 | 91精品国产乱码久久久久久久久 | 亚洲一区二区三区免费 | 国产精品亚洲一区 | 欧美一级欧美一级在线播放 | 国产aaaaav久久久一区二区 | 精品无码久久久久国产 | 色综久久 | av超碰| 日韩h| 中文字幕成人 | 精品国产91乱码一区二区三区 |