React 18 的新功能

Mondo 科技 更新 2024-02-12

新功能:自動批處理Batching是指React將多個狀態更新分組到單個重新渲染中,以獲得更好的效能。 如果沒有自動批處理,我們只在 react 事件處理程式中批處理更新。 預設情況下,React 不會正確。

Promise、settimeouts、本機事件處理程式或任何其他事件。 通過自動批處理,這些更新將分批自動處理。

之前:批處理只在 react 事件上執行 settimeout(()=>, 1000); 之後:對超時、承諾、本機事件處理程式或任何其他事件中的更新進行批處理。 settimeout(()=> ,1000);
更新內容: 過渡是 React 中的乙個新概念,用於區分緊急更新和非緊急更新。

緊急更新反映直接互動,如鍵入、點選、按下等。 轉換更新將 UI 從乙個檢視轉換到另乙個檢視。 打字、點選或按下等緊急更新需要立即響應,以符合我們對物理物件行為方式的直覺。 否則,他們會覺得“有些不對勁”。 但是,轉換是不同的,因為使用者不希望在螢幕上看到每個中間值。

例如,當您在下拉選單中選擇過濾器時,您希望過濾器按鈕本身在您單擊它時立即做出反應。 但是,實際結果可能會單獨轉換。 乙個小的延遲是難以察覺的,而且通常是意料之中的。 而且,如果在呈現結果之前再次更改篩選器,則只關心檢視最新結果。

通常,為了獲得最佳使用者體驗,使用者輸入應同時導致緊急更新和非緊急更新。 你可以在輸入事件中使用 StartTransition API 來告訴 React 哪些是緊急更新,哪些是“過渡”:

import from 'react';緊急:顯示輸入內容setinputvalue(input); 將內部的任何狀態更新標記為 transitiontransition((()=>)。
StartTransition 中包裝的更新被視為非緊急更新,如果發生更緊急的更新(如單擊或擊鍵),則會中斷。 如果轉換被使用者打斷(例如,在一行中輸入多個字元),React 會丟棄未完成的無效渲染,只渲染最新的更新。

UseTransition:啟動轉換的掛鉤,包括用於跟蹤掛起狀態的值。 starttransition:一種在鉤子不可用時啟動轉換的方法。 過渡將選擇併發渲染,這允許中斷更新。 如果內容再次暫停,過渡還會告訴 React 繼續顯示當前內容,同時在後台呈現過渡內容。

新的懸念功能允許您以宣告方式指定載入狀態,如果元件樹的一部分尚未準備好顯示

Suspense 使“UI 載入狀態”成為 React 程式設計模型中第一種宣告性概念。 這使我們能夠在其之上構建更高階別的功能。 

幾年前,我們推出了限量版的懸疑。 但是,唯一支援的用例是 react延遲拆分**,在伺服器端渲染時完全不支援。

在 React 18 中,我們新增了對 Suspense 的伺服器端支援,並通過併發渲染擴充套件了其功能。

React 18 中的懸念在與暫存 API 結合使用時效果最佳。 如果你在過渡期間掛起,React 將阻止已經可見的內容被回退替換。 相反,React 會延遲渲染,直到有足夠的資料可以載入以防止載入狀態不佳。

新的客戶端和伺服器端渲染 API在此版本中,我們藉此機會重新設計了為客戶端和伺服器端渲染公開的 API。 這些更改允許使用者在公升級到 React 18 中的新 API 時繼續使用 React 17 模式下的舊 API。

react dom client

這些新 API 現在從 react-dom 客戶端匯出:

createroot:一種建立要渲染或解除安裝的根的新方法。 用它來替代 reactdomrender。沒有它,React 18 的新功能將無法執行。 hydrateroot:一種用於建立伺服器端渲染應用程式的新方法。 用它來替代 reactdomHydrate 與新的 React DOM 伺服器端 API 配合使用。 沒有它,React 18 的新功能將無法執行。 CreateRoot 和 HydrateRoot 都接受乙個名為 OnRecoverableError 的新選項,以防您希望在 React Render 或 Hydrate 從文件錯誤中恢復時收到通知。 預設情況下,React 使用。

report錯誤,或在較舊的瀏覽器中使用控制台error。

react dom server

這些新的 API 現在從 react-dom 伺服器匯出,並完全支援流式處理 Suspense::

rendertopipeablestream:用於 Node 環境。 RenderToReadableStream:用於現代邊緣執行時環境,例如 Deno 和 Cloudflare Workers。 現有的 rendertostring 方法仍然可用,但不建議這樣做。

新的嚴格模式行為 將來,我們希望新增乙個功能,允許 React 在保留狀態的同時新增和刪除部分 UI。 例如,當使用者從乙個螢幕不剪輯並切換回來時,React 應該能夠立即顯示前乙個螢幕。 為此,React 將使用與之前相同的元件狀態解除安裝並重新載入樹。

此功能將為 React 應用程式提供更好的開箱即用效能,但要求元件能夠適應多次載入和銷毀的效果。 大多數效果無需任何更改即可工作,但有些效果會假設它們只載入或銷毀一次。

為了幫助發現這些問題,React 18 引入了乙個新的僅限開發的嚴格模式檢查。 每當首次掛載元件時,此檢查將自動解除安裝並重新載入每個元件,並在第二次掛載時返回到其先前的狀態。

在此更改之前,React 將載入元件並建立效果:

React 掛載元件布局 效果建立 效果建立
在 React 18 的嚴格模式下,React 模擬了開發模式下的解除安裝和過載元件:

* React 掛載元件 * 布局效果建立 * 效果建立 * React 模擬解除安裝元件 * 布局效果破壞 * 效果銷毀 * React 模擬載入元件(使用之前的狀態) * 布局效果建立 * 效果建立
新鉤子useid

UseId 是乙個新的鉤子,用於在客戶端和伺服器上生成唯一 ID,以避免水合物不匹配。 它主要用於整合需要唯一 ID 的輔助功能 API 的元件庫。 這解決了 React 17 及更低版本中已經存在的問題,但在 React 中

18 甚至更重要,因為新的流式伺服器端渲染器對 HTML 的無序交付。

usetransition

UseTransition 和 StartTransition 允許您將某些狀態更新標記為不緊急。 預設情況下,其他狀態更新被視為緊急。 react

緊急狀態更新(例如,更新文字輸入)將被允許中斷非緊急狀態更新(例如,呈現搜尋結果列表)。

usedeferredvalue

useDeferredValue 允許您推遲重新呈現樹的非緊急部分。 它類似於 Debounce,但與它相比有一些優勢。 它沒有固定的時間延遲,一旦第乙個渲染反映在螢幕上,React 就會嘗試延遲渲染。 延遲呈現是可中斷的,並且不會阻止使用者輸入。

usesyncexternalstore

UseSyncExternalStore 是乙個新掛鉤,它允許外部儲存通過強制更新到 Store 進行同步來支援併發讀取。 在實現對外部資料來源的訂閱時,它消除了對 useeffect 的需要,並且建議用於與 React 相關的任何內容

用於外部狀態整合的庫。

useinsertioneffect

UseInsertionEffect 是乙個新的鉤子,它允許 css-in-js 庫解決在渲染中注入樣式的效能問題。 除非你已經建立了乙個css-in-js庫,否則我們不希望你使用它。 這個鉤子將在 dom 更改後執行,但在 .

閱讀新布局前的布局效果。 這解決了 React 17 及更低版本中已經存在的問題,但在 React 18 中更為重要,因為 React 在併發渲染時會向瀏覽器讓步,讓它有機會重新計算布局。

併發模式(CM)是乙個我們可能已經聽說過很多次的概念,但實際上這個概念在去年已經成熟了,在React 17中,可以通過一些實驗性API開啟CM。

併發模式可幫助應用保持響應狀態,並根據使用者的裝置效能和 Internet 速度進行適當調整,並通過使渲染可中斷來修復阻塞呈現限制。 在 Concurrent 模式中,React 可以同時更新多個狀態。

說得太複雜可能有點尷尬,但可以用一句話來概括:React 17 和 React 18 的區別在於,它從同步不可中斷更新轉變為非同步可中斷更新。

為了更好地管理根節點,React 18 引入了乙個新的根 API,該 API 也支援 New Concurrent Renderer,它允許你進入併發模式。

// react 17import react from 'react';import reactdom from 'react-dom';import app from './app';const root = document.getelementbyid('root')!;reactdom.render(, root);// react 18import react from 'react';import reactdom from 'react-dom/client';import app from './app';const root = document.getelementbyid('root')!;reactdom.createroot(root).render();
在 React 18 中,提供了新的根 API,我們只需要將 render 公升級到 createroot(root) 即可。render() 啟用併發模式。

這時,可能會有同學問:開啟併發模式是否意味著開啟了併發更新?

no!在 React 17 的一些實驗性特性中,開啟併發模式意味著開啟併發更新,但在 React 18 正式發布後,由於官方策略的調整,React 不再依賴併發模式來開啟併發更新。

換言之:併發模式已啟用,但不一定啟用併發更新!

一句話:在 18 中,不再有多種模式,而是是否啟用併發更新取決於是否使用併發功能。

從體系結構的角度來看,目前有兩種體系結構:

更新以不可中斷的遞迴方式進行stack reconciler(舊體系結構)使用可中斷遍歷進行更新fiber reconciler新架構可以選擇是否啟用併發更新,因此目前市場上的所有 React 版本都有四種情況:

舊架構(v15 及更早版本)新架構,不啟用併發更新,行為與案例 1 相同(預設為 v16 和 v17 中的情況) 新架構,不啟用併發更新,但啟用併發模式和一些新功能(比如自動批處理,預設為 v18 中的情況) 新架構, 啟用併發模式,並啟用併發更新併發功能是指開啟併發模式後才能使用的功能如:

UseDeFerRedValueUseTransitionStartTransition 併發是新 API 的乙個示例,它可以通過將特定更新標記為“轉換”來顯著改善使用者互動,這僅僅是因為由 StartTransition 中包裝的 setstate 觸發的渲染被標記為非緊急渲染,可能會被其他緊急渲染搶占。

import react, from 'react';const app: react.fc = ()=> )return ( 

}export default app;

UseDeferRedValue 併發功能: 示例:從介紹來看,useDeferredValue 和 UseTransition 感覺相似嗎?

相同:UseDeferredValue 與 UseTransition 的內部實現基本相同,後者被標記為延遲更新任務。 不同:UseTransition 將更新任務轉換為延遲更新任務,useDeferredValue

是生成乙個新值,該值充當延遲狀態。 (乙個用於包裝方法,另乙個用於包裝值)。

所以,在上面的 starttransition 示例中,我們也可以使用 useDeferredValue:

import react, from 'react';const app: react.fc = ()=> ,使用併發功能,啟用併發更新 const deferredlist = useDeferredValue(list);  return ( 

}export default app;

此時,我們的任務被拆分為每幀不同的任務,JS指令碼執行時間在5ms左右,這樣瀏覽器就有時間進行樣式布局和樣式繪製,減少了掉幀的可能性。

React 18 通過預設執行批處理來實現開箱即用的效能改進。

批處理是指在資料層將多個狀態更新批處理為單個更新以獲得更好的效能(在檢視層,將多個渲染合併為單個渲染)。

在 React 18 之前:在某些情況下,更新沒有被合併在 React 18 之前,我們只在 React 事件處理程式中進行了批量更新。 預設情況下,在Promise、setTimeout 和本機事件處理程式或任何其他活動不會對任何更新進行批處理:

案例 1:React 事件處理程式

以下 ** 將被批處理,並且只會呈現頁面一次。

import react, from 'react';在 react 18 之前,const app: reactfc = ()=> }count2 is $`export default app;
場景 2:settimeout

如果我們把狀態的更新放在promisesettimeout在內部,元件被渲染兩次,並且不會批量更新。

import react, from 'react';在 react 18 之前,const app: reactfc = ()=> ) 不會在 setTimeout }}count1 中批處理:

count2:

}export default app;

場景 3:原生 JS 事件

在原生 JS 事件中,結果與情況 2 相同,每次單擊“更新兩個狀態”時,元件都會渲染兩次,並且不會進行批量更新。

import react, from 'react';在 react 18 之前,const app: reactfc = ()=> ) 不會在原生 JS 事件中批處理 }, return (count1:

count2:

}export default app;

在 React 18 中:合併更新 在 React 18 中,上面的三個示例只有乙個渲染,因為所有更新都會自動批處理。 這無疑是應用程式整體效能的良好改進。

但是,以下示例將在 React 18 中執行兩次渲染

import react, from 'react';// react 18const app: react.fc = ()=> }count1: 

count2:

}export default app;

總結:

在 18 之前,批處理僅在 react 事件處理程式中自動完成,否則它會在 18 之後多次更新,並且在任何情況下都會自動批處理,將多個更新合併為乙個批處理是乙個重大更改,如果您想選擇退出批量更新,您可以使用 flushsync:

import react, from 'react';import from 'react-dom';const app: react.fc = ()=> ) 第一次更新 flushsync((()=> ) 第二次更新 }}count1:

count2:

}export default app;

Suspense 不再需要回退來捕獲空的回退屬性,並且該屬性的處理方式也發生了變化:不再跳過缺失或空回退的懸念邊界。

更新前

以前,如果你的 Suspense 元件沒有提供回退屬性,React 會悄悄地跳過它並繼續搜尋下乙個邊界:

react 17const app = ()=> > < - 使用此邊框,顯示載入元件 < - 跳過此邊框,無後備屬性);export default app;
更新後

React 現在將使用當前元件的懸念作為邊界,即使當前元件的懸念值為 null 或 undefined:

react 18const app = ()=> > < - 不使用 < - 使用此邊框,將回退渲染為 null );export default app;
乙個 React 元件的返回值在 React 17 中,如果需要返回乙個空元件,React 只允許 null。 如果顯式返回 undefined,控制台將在執行時引發錯誤。 在 react 18 中,不再檢查由於返回 undefined 而導致的崩潰。 它可以返回 null 和 undefined(但 React 18 中的 DTS 檔案仍然會檢查並且只允許返回 null,因此您可以忽略此型別錯誤)。 併發更新的含義是交替不同的任務,當預留的時間不夠時,React 將執行緒的控制權返回給瀏覽器,等待下一幀時間到來,然後繼續中斷的工作併發模式是實現併發更新的基本前提,時間切片是實現併發更新的具體手段。

相關問題答案

    找出 Mocui 的特點是什麼

    翡翠家族是翡翠的一種特殊型別,其顏色為黑色或深色墨水,與其他翡翠相比,翡翠的特性也有其獨特性。本文將詳細介紹祖母綠的特徵,以幫助您更好地了解和識別這種特殊的翡翠品種。首先,油墨的顏色是其最明顯的特徵之一。墨水的黑色或深色墨水顏色分布不均勻,而是由深色和淺色的混合組成。其中,深色部分通常為黑色或深色墨...

    EPE包裝材料有哪些環保特點?

    隨著環保意識的不斷增強,人們對包裝材料的要求也越來越高。EPE包裝材料作為一種新型的環保包裝材料,在市場上受到了廣泛的關注。那麼,EPE包裝材料有哪些環保特點呢?首先,它可以重複使用。EPE包裝材料是一種可以重複使用的環保材料。使用後,EPE包裝材料經過加工和回收後,可以在包裝領域進行加工和再利用。...

    摩擦帶有哪些特點?哪些因素會影響其效能?

    摩擦帶是指石棉和非石棉橡膠銅絲制動帶,廣泛用於工農業機械的制動減速和動力傳動。其良好的彈性 抗衝擊性和高耐磨性使摩擦帶在各種複雜的工況下工作,達到安全可靠的制動效果。摩擦帶有什麼特點?摩擦帶由石棉或無石棉橡膠銅線製成,具有許多優良的效能。良好的彈性和韌性 這使得摩擦帶能夠承受較大的衝擊和壓力,同時還...

    鐵氟龍環形輸送帶有哪些特點

    鐵氟龍環形帶作為一種特殊型別的皮帶,具有許多獨特的效能,使其在許多應用中表現出色。下面就為大家詳細介紹一下鐵氟龍環形輸送帶的特點。首先,鐵氟龍環形輸送帶具有優良的耐高溫效能。由於其製造材料聚四氟乙烯 PTFE 的高熔點,特氟龍輸送帶可以在非常高的溫度下執行,通常可承受高達 C 的溫度。這一特性使得鐵...

    聚乙烯PE有哪些特點? UV膠可以粘接聚乙烯PE嗎?

    聚乙烯 PE 是一種聚合物,是由乙烯單體聚合反應形成的合成塑料。以下是聚乙烯的一些主要化學性質 .化學式 聚乙烯的基本化學式是 CH N,其中N表示重複單元數。.結構 聚乙烯是由乙烯分子的重複單元組成的線性聚合物。乙烯分子的結構式為CH CH,它們通過共價鍵連線形成長鏈聚合物。.熔點 聚乙烯通常具有...