原文鏈接
2022 年 3 月 29 日,React 18 正式版發布了,
新增了以下這些新功能
Concurrent Mode 并發模式
在 CM 模式下,React 在執行程序中,每執行一個 Fiber,都會看看有沒有更高優先級的更新,如果有,則當前低優先級的的更新會被暫停,待高優先級任務執行完之后,再繼續執行或重新執行,
startTransition
React 的狀態更新可以分為兩類:
- 緊急更新(Urgent updates):比如打字、點擊、拖動等,需要立即回應的行為,如果不立即回應會給人很卡,或者出問題了的感覺
- 過渡更新(Transition updates):將 UI 從一個視圖過渡到另一個視圖,不需要即時回應,有些延遲是可以接受的,
默認的setState是緊急更新,startTransition包裹的setState是非緊急更新,
React 會在高優先級更新渲染完成之后,才會啟動低優先級更新渲染,并且低優先級渲染隨時可被其它高優先級更新中斷,
// 緊急的
setInputValue(e.target.value);
startTransition(() => {
setSearchQuery(input); // 非緊急的
});
自動批處理 Automatic Batching
批處理是指 React 將多個狀態更新,聚合到一次 render 中執行,以提升性能,
在 React 18 之前,React 只會在事件回呼中使用批處理,而在 Promise、setTimeout、原生事件等場景下,是不能使用批處理的,
而在 React 18 中,所有的狀態更新,都會自動使用批處理,不關心場景,
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// React 只會 re-render 一次,這就是批處理
}
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React 只會 re-render 一次,這就是批處理
}, 1000);
如果你在某種場景下不想使用批處理,你可以通過 flushSync來強制同步執行
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React 更新一次 DOM
flushSync(() => {
setFlag(f => !f);
});
// React 更新一次 DOM
}
注意:自動批處理情況下在 Class 組件中,如果你在兩次 setState 中間讀取了 state 值,會出現不兼容的情況
// 不兼容
handleClick = () => {
setTimeout(() => {
this.setState(({ count }) => ({ count: count + 1 }));
// 在 React17 及之前,列印出來是 { count: 1, flag: false }
// 在 React18,列印出來是 { count: 0, flag: false }
console.log(this.state);
this.setState(({ flag }) => ({ flag: !flag }));
});
};
// 更改后兼容
handleClick = () => {
setTimeout(() => {
ReactDOM.flushSync(() => {
this.setState(({ count }) => ({ count: count + 1 }));
});
// 在 React18,列印出來是 { count: 1, flag: false }
console.log(this.state);
this.setState(({ flag }) => ({ flag: !flag }));
});
};
流式 SSR
SSR 一次頁面渲染的流程大概為:
- 服務器 fetch 頁面所需資料
- 資料準備好之后,將組件渲染成 string 形式作為 response 回傳
- 客戶端加載資源
- 客戶端合成(hydrate)最終的頁面內容
而在 React 18 中,基于全新的 Suspense,支持了流式 SSR,也就是允許服務端一點一點的回傳頁面,
在 React 18 中,我們通過 Suspense包裹,可以告訴 React,我們不需要等這個組件,可以先回傳其它內容,等這個組件準備好之后,單獨回傳,
更多關于流式 SSR 的講解可見:https://github.com/reactwg/react-18/discussions/37
新 Hooks
useDeferredValue
useDeferredValue 可以讓一個 state 延遲生效,只有當前沒有緊急更新時,該值才會變為最新值,useDeferredValue 和 startTransition 一樣,都是標記了一次非緊急更新,
useId
支持同一個組件在客戶端和服務端生成相同的唯一的 ID,避免 hydration 的不兼容,原理是每個 id 代表該組件在組件樹中的層級結構,
useSyncExternalStore
useSyncExternalStore 能夠讓 React 組件在 Concurrent Mode 下安全地有效地讀取外接資料源,在 Concurrent Mode 下,React 一次渲染會分片執行(以 fiber 為單位),中間可能穿插優先級更高的更新,假如在高優先級的更新中改變了公共資料(比如 redux 中的資料),那之前低優先的渲染必須要重新開始執行,否則就會出現前后狀態不一致的情況,useSyncExternalStore 一般是三方狀態管理庫使用,一般我們不需要關注,
useInsertionEffect
這個 Hooks 只建議 css-in-js庫來使用,這個 Hooks 執行時機在 DOM 生成之后,useLayoutEffect 生效之前,一般用于提前注入 <style></style>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/468077.html
標籤:其他
上一篇:前端開發中需要搞懂的字符編碼知識
