您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關React中并發功能的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
React 是一個開源 JavaScript 庫,開發人員使用它來創建基于 Web 和移動的應用程序,并且支持構建交互式用戶界面和 UI 組件。React 是由 Facebook 軟件工程師 Jordan Walke 創建,React 的第一個版本在七年前問世,現在,Facebook 負責維護。React框架自首次發布以來,React 的受歡迎程度直線飆升,熱度不減。
2020 年 10 月,React 17 發布了,但令人驚訝的是——“零新功能”。當然,這并不是真的表示沒有任何新添加的功能,讓廣大程序員使用者興奮。事實上,這個版本為我們帶來了很多重大功能的升級及16版本的bug修復,并推出了:Concurrent Mode 和Suspense。
雖然這兩個功能尚未正式發布,這些功能已提供給開發人員進行測試。一旦發布,它們將改變 React 呈現其 UI 的方式,從而達到雙倍提高性能和用戶體驗。
簡要說明, Concurrent Mode 和Suspense 可以使用戶無縫處理數據加載,加載狀態,用戶界面操作更加平滑和無縫切換。 在Concurrent Mode 下,React可以暫停高消耗的,非緊急的組件的渲染,并聚焦在更加緊迫的任務處理,如UI 渲染,始終保持應用為可響應式,避免白屏,卡頓等現象。
本文主要分享深入了解Concurrent Mode 和Suspense 模式下的數據提取功能。
眾所周知,JavaScript 框架或庫是單線程的工作。因此,當一個代碼塊運行時,其余的塊必須等待執行。無法并發執行多線程工作。界面渲染也是一樣的。
一旦 React 開始渲染某些東西,無法中斷直到運行完成。React 開發人員將這種渲染稱為“阻塞渲染”。 這種阻塞渲染會創建一個不穩定的用戶界面,并且隨時可能停止響應。
假如,我們需要顯示一個很長的可選列表用于過濾產品的應用程序。我們使用搜索框用于過濾記錄,設計方案是當用戶點擊搜索按鈕后,用戶界面需要重新刷新列出相關聯的數據。
如果列表過長,數據過多,UI“卡頓”,即渲染對用戶可見。這種卡頓也會大大降低產品性能。開發人員可以使用一些技術,如節流和防抖,這些技術會有一定幫助,但不是完美的解決方案。
節流限制特定函數被調用的次數。使用節流,我們可以避免重復調用昂貴和耗時的API或函數。這個過程能夠提高性能,尤其是在用戶界面上呈現信息。
防抖會在預定的時間內忽略對函數的調用。函數調用僅在經過預定時間后進行。
下圖描述了卡頓現象:
在等待非緊急 API 調用完成時,UI 卡頓,從而阻止呈現用戶界面。解決方案是使用并發模式進行可中斷渲染。
通過可中斷渲染,React.js 在處理和重新渲染列表時不會阻塞 UI。它通過暫停瑣碎的工作、更新 DOM 并確保 UI 不會卡頓,使 React.js 更加細化。React 使用用戶輸入并行更新或重繪輸入框。React 使用用戶輸入并重繪輸入框并行執行。它還更新內存中的列表。React 完成更新后,它會更新 DOM 并在用戶的顯示器上重新呈現列表。本質上,無中斷渲染使 React 能夠“多任務”。此功能提供了更流暢的 UI 體驗。
并發模式是一組功能,可幫助 React 應用程序保持響應并平滑地適應用戶的設備和網絡速度能力。并發模式將其擁有的任務劃分為更小的塊。 React 的調度程序可以挑選并選擇要執行的作業。作業的調度取決于它們的優先級。通過對任務進行優先級排序,它可以停止瑣碎或不緊急的事情,或者進一步推動它們。 React 始終將用戶界面更新和渲染放在首位。
使用并發模式,我們可以:
控制首次渲染過程
優先處理渲染過程
暫停和恢復組件的渲染
緩存和優化組件的運行時渲染
隱藏顯示內容直到需要展示時
隨著 UI 渲染,并發模式改進了對傳入數據的響應,懶加載控件,異步處理過程。并發模式保證了用戶界面始終處于激活狀態,并且持續在后臺更新數據,并發模式也始終使用React 的兩個鉤掛:useTransition
和useDeferredValue
使用useDeferredValue Hook
useDeferredValue Hook
的定義如下:
const deferredValue = useDeferredValue(value, { timeoutMs: <some value> });
此命令設置值在timeoutMs
中設置的時間后“滯后”。 用戶界面是必須立即更新還是必須等待數據,該命令使用戶界面保持激活狀態和響應性,該Hook避免了 UI 卡頓,并始終保持用戶界面響應,以保持獲取數據滯后的較小成本。
useTransition Hook
是React
中主要用于掛起的Hook
,假設這樣的場景下:其中有一個帶有用戶名按鈕的網頁。只需點擊一個按鈕,網頁就會在屏幕上顯示用戶的詳細信息。
假設用戶首先單擊一個按鈕,然后單擊下一個。屏幕要么變成空白,要么我們在屏幕上看到一個微調器。如果獲取詳細信息花費的時間太長,用戶界面可能會凍結。useTransition
方法返回兩個Hook
的值:startTransition
和 isPending
。定義的語法如下:
const [startTransition, isPending] = useTransition({ timeoutMs: 3000 });
startTransition
定義的語法:
<button disabled={isPending} startTransition(() => { <fetch Calls> }); </button> {isPending? " Loading...": null}
使用 useTransition
鉤子,React.js
繼續顯示沒有用戶詳細信息的用戶界面,直到用戶詳細信息準備好,但 UI 是響應式的。React
優先考慮用戶界面,以在并行獲取數據時保持響應。
Suspense
是React
與并發模式一起引入的另一個實驗性功能。Suspense
使組件能夠在渲染前等待一段預定的時間。Suspense
的主要作用是從組件異步讀取數據,而無需擔心數據的來源。Suspense
最適合延遲加載的概念。Suspense
允許數據獲取庫通知React
數據組件是否可以使用。在必要的組件準備就緒之前,React
不會更新 UI。
使用Suspense
的好處:
1.數據獲取庫和React
組件之間的集成
2.控制視覺加載狀態
3.避免競爭條件
Spinner
組件的基本語法如下:
import Spinner from './Spinner'; <Suspense fallback={<Spinner />}> <SomeComponent /> </Suspense>
Concurrent Mode
中使用的Suspense
允許耗時的組件在等待數據的同時開始渲染。同時顯示占位符。這種組合產生了更流暢的UI體驗。
React.lazy
是一個新功能,它使React.js
能夠延遲加載組件。懶加載意味著僅在需要時才加載組件(檢索和呈現它們的代碼)。他們會優先考慮最關鍵的用戶界面組件。React
開發人員建議將懶加載組件包裝在Suspense
組件中。
這樣做可確保組件在渲染時不會出現“不良狀態”。用戶界面在整個過程中保持響應,并帶來更流暢的用戶體驗。
啟用并發模式
要啟用并發模式,請安裝最新的測試版本。安裝 React 的先決條件是節點數據包管理器 (npm)。要安裝測試版本,請執行以下命令:
npm install react@experimental react-dom@experimental
要測試是否設置了測試版本,請創建一個示例 React 應用程序。沒有測試功能的渲染代碼如下:
import * as React from 'react'; import { render } from 'react-dom'; render(<App />, document.getElementById('root'));
并發模式的,具體代碼如下:
import * as React from 'react'; import { createRoot } from 'react-dom'; createRoot(document.getElementById('root')).render(<App />);
這將為整個應用程序啟用并發模式。React 將渲染調用分為兩部分:
創建根元素
使用渲染調用
目前,React 計劃維護三種模式:
傳統模式是向后兼容的傳統或當前模式
阻塞模式是并發模式開發的中間階段
并發模式
阻塞模式是使用createBlockingRoot 調用來替換createRoot 調用,在并發模式的開發情況下,阻塞模式為開發者提供了機會來修復bug或解決問題。
React 官方文檔中也說明了每種模式支持的功能:
本文也創建了一個測試程序來驗證并發模式和其他模式的用法和效果。本文以像素應用為例在150*150的畫布上隨機分布像素并包含一個搜索框,每次用戶點擊搜索框時候,畫布會重新渲染自己。
即使UI 界面無法在并發模式下渲染,用戶輸入也不會停止更新。像素畫布在處理完成后重新渲染。在傳統模式下,快速鍵入時,UI 會停止,有時會在再次渲染畫布之前停止。用戶輸入也會停止并且不會更新。
構建像素應用程序的主要文件是 canvas.js。我們還制作了一個輸入框,用戶可以在其中輸入任何內容。每次按下一個鍵都會重新渲染像素畫布。
代碼示例:Index.js
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; // Traditional or non-Concurrent Mode react const rootTraditional = document.getElementById("root"); ReactDOM.render(<App caption="Traditional or Block Rendering" />, rootTraditional); // Concurrent Mode enabled const rootConcurrent = document.getElementById("root-concurrent"); ReactDOM.createRoot(rootConcurrent).render(<App caption="Interruptible Rendering" />);
App.js
import React, { useState, useDeferredValue } from "react"; import "./App.css"; import { Canvas } from "./Canvas"; export default function App(props) { const [value, setValue] = useState(""); //This is available only in the Concurrent mode. const deferredValue = useDeferredValue(value, { timeoutMs: 5000 }); const keyPressHandler = e => { setValue(e.target.value); }; return ( <div className="App"> <h2>{props.caption}</h2> <input onKeyUp={keyPressHandler} /> <Canvas value={deferredValue} /> </div> ); }
Canvas.js
import React from "react"; const CANVAS_SIZE = 70; const generateRandomColor = () => { var letters = "0123456789ABCDEF"; var color = "#"; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; }; const createCanvas = (rows, columns) => { let array = []; for (let i = 0; i < rows; i++) { let row = []; for (let j = 0; j < columns; j++) { row.push(0); } array.push(row); } return array; }; //This is the square with the pixels const drawCanvas = value => { const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE); return canvas.map((row, rowIndex) => { let cellsArrJSX = row.map((cell, cellIndex) => { let key = rowIndex + "-" + cellIndex; return ( <div style={{ backgroundColor: generateRandomColor() }} className="cell" key={"cell-" + key} /> ); }); return ( <div key={"row-" + rowIndex} className="canvas-row"> {cellsArrJSX} </div> ); }); }; export const Canvas = ({ value }) => { return ( <div> <h3 style={{ minHeight: 30 }}>{value}</h3> <div className="canvas">{drawCanvas(value)}</div> </div> ); };
Index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta name="theme-color" content="#000000" /> <title>React App Concurrent Mode</title> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="container"> <div id="root" class="column"></div> <div id="root-concurrent" class="column"></div> </div> </body> </html>
讓我們看看我們的代碼。我們看到的第一個屏幕是初始屏幕。使用傳統或塊渲染是現在React 的做法。可中斷渲染是并發模式的測試功能。我們先看看傳統的渲染工作。
像素畫布在每次擊鍵時重新渲染。在傳統渲染中,整個 UI 會在每次擊鍵時暫停,直到它可以重新渲染屏幕。在此期間,即使我們繼續打字,用戶輸入不會更新。
下圖顯示可中斷渲染。在可中斷渲染中,用戶可以繼續輸入。在為每次擊鍵并行重新渲染畫布時,UI 不會停止或停止。
重新渲染完成后,React 會更新 UI。雖然在靜態截圖中很難看到,但我們可以看到網格在變化,但用戶仍然可以打字而不會出現 UI 卡頓的情況。
關于“React中并發功能的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。