日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React 18 带给我们的惊喜

發(fā)布時間:2023/12/9 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React 18 带给我们的惊喜 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

大家好,我是若川。持續(xù)組織了8個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構(gòu)系列》?包含20余篇源碼文章。歷史面試系列

這篇文章發(fā)布于3.28日,3.29日 react 18 發(fā)布。

1、前言

React 18 的 alpha 版已經(jīng)發(fā)布有段時間了,之前學習后由于沒有開發(fā)實踐結(jié)合去思考,對 React 18 的意義認識并不深刻。前段時間做了一些老舊項目遷移,發(fā)現(xiàn)復雜項目下每次渲染都要精心調(diào)整,否則就會有麻煩的性能或體驗瑕疵,而 React 內(nèi)部渲染順序和優(yōu)先級很難調(diào)整,就導致總體體驗差了點意思。回顧了 React 18 的三個新特性,有種久旱逢甘雨的欣喜。

團隊內(nèi)部推行了 React hook,好處就不在這里贅述了,也陸續(xù)收到了一些負面反饋。其一就是 React hook 更加趨向面向數(shù)據(jù)實體進行拆分,而一個動作需要多個數(shù)據(jù)實體協(xié)作,例如一個 Modal Form 需要 visible 和 data 兩個數(shù)據(jù)項協(xié)作,但是這兩個數(shù)據(jù)項的變更會觸發(fā)兩次渲染結(jié)算,增加性能開銷。

作者之前遇到過復雜 Form 表單下,初次渲染由于數(shù)據(jù)項過于復雜導致無限次 render 的 bug。在這個 case 中,核心的沖突就是在數(shù)據(jù)項復雜度提升的同時,React Diff 的性能就遇到了“偽瓶頸”。這里不是說 React Diff 性能差,僅僅想表達它的高性能需要更高的設計理念和實踐經(jīng)驗,這也是相對于 Vue 等更加易學的框架而言,總的來說上限高下限也低。而 React 18 的變化讓我看到了 React 團隊正在關(guān)注這一部分,并且給予了更好的解決方案。

閑聊到此為止,進入正題,給大家介紹下 React 18 的四個重要新特性:

  • Automatic batching

  • Concurrent APIS

  • SSR for Suspense

  • New Render API

2、Automatic batching

在 React 中使用 setState 來進行 dispatch 組件 State 變化,當 setState 在組件被調(diào)用后,并不會立即觸發(fā)重新渲染。React 會執(zhí)行全部事件處理函數(shù),然后觸發(fā)一個單獨的 re-render,合并所有更新。這里舉個簡單例子:

const [count, setCount] = useState(0);function increment() {// setCount(count + 1)// 使用無狀態(tài)函數(shù)進行優(yōu)化,避免多次 re-rendersetCount(c => c + 1); }function handleClick() {increment();increment();increment(); }

最終 React 會將更新函數(shù)放到一個隊列里,然后合并隊列觸發(fā) setCount (3) 的 re-render,這就是 batching 的含義。

這樣既可以減少程序數(shù)據(jù)狀態(tài)存在中間值導致的不穩(wěn)定性,也可以提升渲染性能。但是可惜的是在 React 18 之前,如果在回調(diào)函數(shù)的異步調(diào)用中,執(zhí)行 setState,由于丟失了上下文,無法做合并處理,所以每次 setState 調(diào)用都會觸發(fā)一次 re-render。

function handleClick() {// React 18 以前的版本(/*...*/).then(() => {setCount((c) => c + 1); // 立刻重渲染setFlag((f) => !f); // 立刻重渲染}); }

而 React 18 帶來變化便是,任何情況下都可以合并渲染了!

如果你希望在 React 18 的 setState 后立即執(zhí)行重新渲染, 只需要使用 flushSync 包裹即可。

function handleClick() {// React 18+fetch(/*...*/).then(() => {ReactDOM.flushSync(() => {setCount((c) => c + 1); // 立刻重渲染setFlag((f) => !f); // 立刻重渲染});}); }

回歸到實際開發(fā)中,Automatic batching 機制讓我們有能力對渲染順序和節(jié)奏進行一些基礎的把控。例如在 Canvas 畫布編輯場景中,我們可以加載完主節(jié)點框架之后立刻進行渲染,而每個節(jié)點的內(nèi)容則可以進行合并渲染,盡可能加快用戶看到可編輯頁面的時間,同時避免 http 異步函數(shù)引起的頻繁渲染的性能開銷。

3、Concurrent APIS

在官方視頻中明確指出了 React 18 中并不存在 Concurrent Mode,只有用于并發(fā)渲染的并發(fā)新特性。開發(fā)者希望能夠在 Web Platform 引入并發(fā)渲染,來實現(xiàn)多個渲染任務的并行渲染,其中 Suspense 就是基于此誕生的。

React 18 提供了三個新的 API 支持這一并發(fā)特性,分別是:

  • startTransition()

  • useDeferredValue()

  • useTransition()

由于 useTransition 的官方文檔并未放出來,這里就僅僅介紹另外兩種 API。

3.1 startTransition()

import { startTransition } from "react";// 緊急更新: setInputValue(input);// 標記回調(diào)函數(shù)內(nèi)的更新為非緊急更新: startTransition(() => {setSearchQuery(input); });

簡單來說,被 startTransition 包裹的 setState 觸發(fā)的渲染被標記為不緊急渲染,意味著他們可以被其他緊急渲染所搶占。這種渲染優(yōu)先級的調(diào)整手段可以幫助我們解決各種性能偽瓶頸,提升用戶體驗。

3.2 useDeferredValue()

這個 hook 適用于設置延遲值,參考官方演示視頻來看。

function Page() {const [filters, mergeFilter] = useMergeState(defaultFilters);const deferedFilters = React.useDeferedValue(filters);return (<Fragment><Filters filters={filters} ><List filters={deferedFilters} ></Fragment>); }

useDeferedValue () 會將 List 組件的渲染變得更加平滑,深層次來看則是 defered value 引起的渲染則會被標記為不緊急渲染,會被 filters 引起的渲染進行搶占,進而達到用戶快速輸入搜索等場景下頁面抖動或者卡頓問題。

4、SSR for Suspense

早在 2018 年,React 就推出了 Suspense 的基礎版本。

它可以在客戶端動態(tài)加載代碼(React.lazy),配合 Suspense 組件實現(xiàn)數(shù)據(jù)拉取和狀態(tài)控制的關(guān)注點分離(當子組件未加載完成時,父組件填充 fallback 聲明的組件),但是并不能在服務器端進行加載。

<Suspense fallback={<Skeleton />}><Header /><Suspense fallback={<ListPlaceholder />}><ListLayout /></Suspense> </Suspense>

React 的開發(fā)者對 Suspense 的期望并不僅僅止步于此,他們認為 Suspense 拓展了我們對組件的概念。在 React 18 中,Suspense 可以運行在服務器端,Server Rendering 的性能不需要受制于性能最差的組件(木桶效應)。

在 React 18 之前,Server Rendering 的流程是服務器端請求所有數(shù)據(jù),然后發(fā)送 HTML 到客戶端或者說瀏覽器,然后由客戶端的 hydrate 內(nèi)容,每個環(huán)節(jié)必須按部就班的執(zhí)行。當 Suspense 可以在服務器端使用之后,一旦某個組件加載慢,就可以將 fallback 的內(nèi)容傳輸?shù)娇蛻舳?#xff08;例如下圖中的 loading 態(tài)),保證用戶盡可能早的可進行交互。

更加優(yōu)秀的部分則是,hydrate 是可以通過用戶的行為來調(diào)整優(yōu)先級的,例如上圖中 Profile 組件和正在 Loading 的評論組件同時處于 Suspense 的流程中,此時用戶點擊評論組件,React 將會優(yōu)先 hydrate 評論組件,盡可能優(yōu)先滿足用戶交互體驗。

回歸到代碼實現(xiàn)細節(jié),整體框架上服務器和客戶端的連接必然趨向于持續(xù)性的長鏈接,因此 res.send 需要變成 res.socket,pipeToNodeWritable 替換 renderToString 并且配合 Suspense 即可(官方例子)。

5、New Render API

新的更加友好的語義化 render 方式。

const container = document.getElementById("app");// 舊 render API ReactDOM.render(<App />, container);// 新 createRoot API const root = ReactDOM.createRoot(container); root.render(<App />);

Client 端提供了新 水合 Hydrate API。

const root = ReactDOM.hydrateRoot(container, <App tab="home" />);

以及 新 useId () API 來為組件生成唯一 ID。

由于 Suspense 和 并發(fā)渲染在 React 18 的大規(guī)模使用,一些具有 External stores 的 API,比如全局變量、document 對象如何在并發(fā)場景下保證一致性呢?如果無法保證一致性,在并發(fā)渲染過程中可能會導致組件展示的不一致。

為了解決這個問題,React 18 提供了 useSyncExternalStore() 這個 hook,來保證獲取 External stores 的一致性。

useSyncExternalStore(// 注冊回調(diào)函數(shù)subscribe: (callback) => Unsubscribe,// 獲取快照函數(shù)getSnapshot: () => state ) => state

具體使用方式參考:

6、React 未來展望

在官方視頻中,開發(fā)者們也對未來版本的內(nèi)容進行介紹。

Support for Data Fetching API

由于 Suspense 的大規(guī)模應用,其數(shù)據(jù)獲取變得更加定制化,目前常見的有 Relay、React Query 等。React 官方也希望將這一部分納入到 React 的 API 中。

Server Component

組件不僅可以通過網(wǎng)絡讀取數(shù)據(jù)、也可以后臺數(shù)據(jù)層直接讀取服務數(shù)據(jù),將大大減少服務器端向客戶端傳輸?shù)拇a量,和同構(gòu)模式十分類似。

React 18 in React Native

2022 年 React 18 將和 React Native 一起發(fā)布,跨平臺構(gòu)建的史詩級更新,RN 并發(fā)的一些老大難將得到解決。

7、結(jié)語

結(jié)合起來看,React 18 關(guān)注點在于更快的性能、用戶交互響應效率和跨平臺構(gòu)建,其設計理念處處包含了中斷與搶占概念。React 18 給我們提供了一些從應用構(gòu)建視角下的手段,例如:

  • 在 Client 端隨時中斷的框架設計,第一優(yōu)先級渲染用戶最關(guān)注的 UI 交互模塊。

  • 從后端到前端 “順滑” 的管道式 SSR,并將 hydration 過程按需化,且支持被更高優(yōu)先級用戶交互行為打斷,第一優(yōu)先水合用戶正在交互的部分。

  • 作為一名前端開發(fā),十分期待 React 18 的到來。

    ·················?若川簡介?·················

    你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學習源碼整體架構(gòu)系列》20余篇,在知乎、掘金收獲超百萬閱讀。
    從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)堅持寫了8年,點擊查看年度總結(jié)。
    同時,最近組織了源碼共讀活動,幫助3000+前端人學會看源碼。公眾號愿景:幫助5年內(nèi)前端人走向前列。

    掃碼加我微信 ruochuan02、拉你進源碼共讀

    今日話題

    略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

    總結(jié)

    以上是生活随笔為你收集整理的React 18 带给我们的惊喜的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。