字元集和字元編碼 字元集就是字元的集合,如常見的 ASCII字元集,GB2312字元集,Unicode字元集等。這些不同字元集之間最大的區別是所包含的字元數量的不同。 字元編碼則代表字元集的實際編碼規則,是用於電腦解析字元的,如 GB2312,GBK,UTF-8 等。字元編碼的本質就是如何使用二進 ...
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 生效之前,一般用於提前註入