React正式發(fā)布v18.0.0

一、前言
本文基于開(kāi)源項(xiàng)目:

https://github.com/facebook/react

React18在幾個(gè)小時(shí)前發(fā)布了release,我們一起來(lái)看看。


重大變化搶先看:自動(dòng)批處理、嚴(yán)格模式、一致的 useEffect 計(jì)時(shí)、更嚴(yán)格的水合錯(cuò)誤、掛起樹總是一致的、帶有懸念的布局效果、新的 JS 環(huán)境要求。
二、新特性
React
useId是一個(gè)新的鉤子,用于在客戶端和服務(wù)器上生成唯一 ID,同時(shí)避免水合不匹配。它主要用于與需要唯一 ID 的可訪問(wèn)性 API 集成的組件庫(kù)。這解決了 React 17 及更低版本中已經(jīng)存在的問(wèn)題,但在 React 18 中更為重要,因?yàn)樾碌牧魇椒?wù)器渲染器如何無(wú)序交付 HTML。
startTransition并useTransition讓您將一些狀態(tài)更新標(biāo)記為不緊急。默認(rèn)情況下,其他狀態(tài)更新被認(rèn)為是緊急的。React 將允許緊急狀態(tài)更新(例如,更新文本輸入)以中斷非緊急狀態(tài)更新(例如,呈現(xiàn)搜索結(jié)果列表)。
useDeferredValue讓您推遲重新渲染樹的非緊急部分。它類似于去抖動(dòng),但與之相比有一些優(yōu)點(diǎn)。沒(méi)有固定的時(shí)間延遲,因此 React 將在第一次渲染反映在屏幕上后立即嘗試延遲渲染。延遲渲染是可中斷的,不會(huì)阻止用戶輸入。
useSyncExternalStore是一個(gè)新的鉤子,它允許外部存儲(chǔ)通過(guò)強(qiáng)制對(duì)存儲(chǔ)的更新同步來(lái)支持并發(fā)讀取。它消除了useEffect在實(shí)現(xiàn)對(duì)外部數(shù)據(jù)源的訂閱時(shí)的需要,并且推薦用于任何與 React 外部狀態(tài)集成的庫(kù)。
useInsertionEffect是一個(gè)新的鉤子,它允許CSS-in-JS 庫(kù)解決在渲染中注入樣式的性能問(wèn)題。除非您已經(jīng)構(gòu)建了 CSS-in-JS 庫(kù),否則我們不希望您使用它。這個(gè)鉤子將在 DOM 發(fā)生變異之后運(yùn)行,但在布局效果讀取新布局之前。這解決了在 React 17 及更低版本中已經(jīng)存在的問(wèn)題,但在 React 18 中更為重要,因?yàn)?React 在并發(fā)渲染期間屈服于瀏覽器,使其有機(jī)會(huì)重新計(jì)算布局。
React DOM Client
react-dom/client

createRootrender: 為or創(chuàng)建根的新方法unmount。使用它代替ReactDOM.render. 沒(méi)有它,React 18 中的新功能就無(wú)法工作。
hydrateRoot: 水合服務(wù)器渲染應(yīng)用程序的新方法。使用它而不是 ReactDOM.hydrate與新的 React DOM 服務(wù)器 API 結(jié)合使用。沒(méi)有它,React 18 中的新功能就無(wú)法工作。
兩者都createRoot接受hydrateRoot一個(gè)新選項(xiàng)onRecoverableError,以防你想在 React 從渲染期間的錯(cuò)誤中恢復(fù)或日志記錄時(shí)收到通知。默認(rèn)情況下,React 將使用reportError, 或console.error在較舊的瀏覽器中。
React DOM Server
react-dom/server
完全支持流式傳輸 Suspense:
renderToPipeableStream: 用于 Node 環(huán)境中的流式傳輸。
renderToReadableStream:適用于現(xiàn)代邊緣運(yùn)行時(shí)環(huán)境,例如 Deno 和 Cloudflare worker。
現(xiàn)有renderToString方法繼續(xù)有效,但不鼓勵(lì)使用。
三、棄用了哪些呢
react-dom
react-dom:ReactDOM.render已棄用。使用它會(huì)警告并在 React 17 模式下運(yùn)行您的應(yīng)用程序。
react-dom:ReactDOM.hydrate已棄用。使用它會(huì)警告并在 React 17 模式下運(yùn)行您的應(yīng)用程序。
react-dom:ReactDOM.unmountComponentAtNode已棄用。
react-dom:ReactDOM.renderSubtreeIntoContainer已棄用。
react-dom/server:ReactDOMServer.renderToNodeStream已棄用。
四、升級(jí)
安裝最新版
npm install react react-dom
# or
yarn add react react-dom


首次安裝的話,在控制臺(tái)中看到一個(gè)警告:

React 18 不再支持 ReactDOM.render。請(qǐng)改用 createRoot。在您切換到新的 API 之前,您的應(yīng)用程序會(huì)像運(yùn)行 React 17 一樣運(yùn)行。

React 18 引入了一個(gè)新的根 API,它為管理根提供了更好的人體工程學(xué)。新的根 API 還啟用了新的并發(fā)渲染器,它允許您選擇使用并發(fā)功能。

createRoot

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);
將unmountComponentAtNode改為root.unmount

root.unmount();
渲染中刪除了回調(diào)

function AppWithCallbackAfterRender() {
  useEffect(() => {
    console.log('rendered');
  });

return <App tab="home" />
}

const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(<AppWithCallbackAfterRender />);
服務(wù)器端渲染

import { hydrateRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = hydrateRoot(container, <App tab="home" />);
// 與 createRoot 不同,您不需要在此處單獨(dú)調(diào)用 root.render()
五、最后
    在我們閱讀完官方文檔后,我們一定會(huì)進(jìn)行更深層次的學(xué)習(xí),比如看下框架底層是如何運(yùn)行的,以及源碼的閱讀。
    這里廣東靚仔給下一些小建議:
在看源碼前,我們先去官方文檔復(fù)習(xí)下框架設(shè)計(jì)理念、源碼分層設(shè)計(jì)
閱讀下框架官方開(kāi)發(fā)人員寫的相關(guān)文章
借助框架的調(diào)用棧來(lái)進(jìn)行源碼的閱讀,通過(guò)這個(gè)執(zhí)行流程,我們就完整的對(duì)源碼進(jìn)行了一個(gè)初步的了解
接下來(lái)再對(duì)源碼執(zhí)行過(guò)程中涉及的所有函數(shù)邏輯梳理一遍


作者:廣東靚仔


歡迎關(guān)注:前端早茶