您需要知道的有關(guān)React 18的新特點(diǎn)
譯文【51CTO.com快譯】業(yè)界期待已久的React 18版本終于要發(fā)布了。據(jù)其團(tuán)隊(duì)透露,他們的React 18 alpha版本及其相關(guān)計(jì)劃,已經(jīng)被“安排在路上了”。而根據(jù)2019年的一項(xiàng)前端框架調(diào)查,React JS已持續(xù)被譽(yù)為最受歡迎的框架之一。因此,開發(fā)人員社區(qū)對(duì)該框架的期望也在逐年攀升。不過,鑒于React 17的最終版在開發(fā)人員社區(qū)中,并不太受歡迎。因此,這次React團(tuán)隊(duì)嘗試添加了各種新的特性與功能,并旨在通過首發(fā)計(jì)劃,來獲取用戶的及時(shí)反饋。
從React 18的準(zhǔn)備過程我們可以了解到,他們召集了一個(gè)由技術(shù)專家、代碼庫貢獻(xiàn)者、培訓(xùn)師、以及開發(fā)人員所組成的小組。我從他們?cè)贕itHub的討論組處收集到的信息可知,他們通過周密的計(jì)劃與開發(fā),希望React 18能夠大放異彩。
React 18的新特性主要涉及到:
- 針對(duì)一些重要的開箱即用性能的改進(jìn)
- 新的并發(fā)功能
- 服務(wù)器端渲染區(qū)域的基礎(chǔ)性改進(jìn)
在本文中,我將基于自己對(duì)于React 18的解釋探索和研究,向您介紹React 18的四個(gè)主要新特性。
1. 并發(fā)性(Concurrency)
并發(fā)性是一種能夠同時(shí)執(zhí)行多項(xiàng)任務(wù)的能力。在React 18中,它是作為主要新特性出現(xiàn)的。下面,讓我們來考慮一個(gè)標(biāo)準(zhǔn)的React應(yīng)用場(chǎng)景。假設(shè)有一個(gè)帶有動(dòng)畫顯示效果的組件界面。用戶可以輸入或單擊界面上對(duì)應(yīng)的React組件。
其動(dòng)態(tài)效果為:當(dāng)用戶輸入文字和點(diǎn)擊按鈕時(shí),其對(duì)應(yīng)的動(dòng)畫效果會(huì)在React的上下文處予以呈現(xiàn)。在此過程中,React必須處理所有的函數(shù)調(diào)用、鉤子調(diào)用、以及事件回調(diào),以保證它們可以同時(shí)發(fā)生。如果React一直把時(shí)間花費(fèi)在渲染動(dòng)畫幀上,而無法對(duì)用戶的輸入做出反應(yīng),那么他們就會(huì)認(rèn)為應(yīng)用程序卡住了。
由于React工作在單線程的進(jìn)程中,因此它必須合并,重新排序,以及優(yōu)先處理某些事件和函數(shù),以便為用戶提供最佳、且高質(zhì)量的使用體驗(yàn)。對(duì)此,React在內(nèi)部使用到了一個(gè)“調(diào)度程序”,專門負(fù)責(zé)對(duì)此類回調(diào)和請(qǐng)求進(jìn)行優(yōu)先級(jí)的排序。
可以說,在React 18之前,用戶并不能控制這些函數(shù)的調(diào)用順序。但是React 18則可以通過Transition API(下文將做詳細(xì)討論),向用戶提供對(duì)于這類事件循環(huán)的各種控制。
2. 自動(dòng)批處理(Automatic Batching)
從概念上說,為了提高性能,一組React將多個(gè)狀態(tài)更新放入一次渲染中的操作,被稱為批處理。通常,當(dāng)同一個(gè)點(diǎn)擊事件中帶有兩個(gè)、或兩個(gè)以上的狀態(tài)更新時(shí),那么React會(huì)將它們作為一次性的重新渲染(re-render)進(jìn)行批處理。例如,在如下代碼段正在運(yùn)行時(shí),當(dāng)您進(jìn)行一次單擊時(shí),盡管您在后臺(tái)設(shè)置為兩個(gè)狀態(tài),但是React也只會(huì)執(zhí)行一次性的代碼渲染:
JavaScript
- function App() {
- const [count, setCount] = useState(0);
- const [flag, setFlag] = useState(false);
- function handleClick() {
- setCount(c => c + 1); // Does not re-render yet
- setFlag(f => !f); // Does not re-render yet
- // React will only re-render once at the end (that's batching!)
- }
- return (
- <div>
- <button onClick={handleClick}>Next</button>
- <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
- </div>
- );
- }
由于合理地避開了那些不重要的重新渲染,因此該機(jī)制對(duì)于性能的維持是十分有利的。同時(shí),它還可以防止組件去渲染那些僅更新了單個(gè)狀態(tài)、卻還處于半完成狀態(tài)的變量,所產(chǎn)生的錯(cuò)誤。您可以假想一個(gè)場(chǎng)景:在您只選擇了第一道菜時(shí),餐廳的服務(wù)員是不會(huì)跑到后廚下單的,而是會(huì)等到您完成了所有菜品的選擇后再去。
不過,React的批量更新時(shí)間并不固定。其原因在于:過去,React只在瀏覽器產(chǎn)生事件(如:用戶的點(diǎn)擊)時(shí),執(zhí)行批量更新,而此處我們是在事件已經(jīng)處理之后,才去更新其狀態(tài)(如:在fetch的回調(diào)中)。請(qǐng)參見如下代碼段:
JavaScript
- function App() {
- const [count, setCount] = useState(0);
- const [flag, setFlag] = useState(false);
- function handleClick() {
- setCount(c => c + 1); // Does not re-render yet
- setFlag(f => !f); // Does not re-render yet
- // React will only re-render once at the end (that's batching!)
- }
- return (
- <div>
- <button onClick={handleClick}>Next</button>
- <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
- </div>
- );
- }
在React 18引入了自動(dòng)批處理的方式之后,無論其狀態(tài)來自何處,它都會(huì)一次性地執(zhí)行重新渲染。當(dāng)然,如果您并不想采取批量處理的方式,則可以按照如下代碼段所示,使用Flash同步,來重新渲染目標(biāo)組件。
3. 讓SSR支持Suspense
在典型的React SSR(服務(wù)器端渲染,Server Side Rendering)應(yīng)用程序中,為了讓服務(wù)端直接返回HTML文本給瀏覽器,應(yīng)用程序通常會(huì)發(fā)生如下的后臺(tái)步驟:
- 服務(wù)器檢索那些必須顯示在UI上的相關(guān)數(shù)據(jù)。
- 服務(wù)器將整個(gè)應(yīng)用程序渲染為HTML,并將其作為響應(yīng)傳輸?shù)娇蛻舳恕?/li>
- 客戶端下載JavaScript包(不包括HTML)。
- 最后,客戶端將JavaScript邏輯連接到HTML上,也就是我們常說的“水合(hydration)”。
當(dāng)然,典型的SSR應(yīng)用程序存在著一個(gè)問題,即:整個(gè)應(yīng)用程序的每一步,都必須在較短的時(shí)間內(nèi)迅速完成之后,才能開始下一步。 如今的React 18通過Suspense組件,能夠?qū)Υ祟悊栴}進(jìn)行合理的改進(jìn)。它會(huì)將應(yīng)用程序分解成為遍歷上述步驟的更小的獨(dú)立單元,以便更快地進(jìn)行交互,并向用戶呈現(xiàn)應(yīng)用的內(nèi)容。
4. 轉(zhuǎn)換(Transition)
作為React 18的一項(xiàng)新功能,Transition API能夠協(xié)助用戶解決,在大數(shù)據(jù)量頁面上出現(xiàn)的頻繁更新的問題。例如,如果需要在已輸入的區(qū)域內(nèi)過濾出數(shù)據(jù)列表,那么您就必須在對(duì)應(yīng)的狀態(tài)中,求解該區(qū)域的值,以分離出數(shù)據(jù),進(jìn)而控制輸入進(jìn)來的字段值。為此,您可以使用“setSearchQuery(input);”來更新輸入值,并搜索結(jié)果。
因此,每當(dāng)有用戶鍵入任何字符時(shí),我們都需要更新輸入值,并使用新的值來查找列表,以最終顯示結(jié)果。而當(dāng)所有的內(nèi)容都被渲染到大數(shù)據(jù)量的頁面上時(shí),這可能會(huì)導(dǎo)致頁面更新的延遲,從而使其他交互或輸入變得緩慢、甚至無響應(yīng)。此外,即使您的列表并不太長(zhǎng),用戶在每次擊鍵列表項(xiàng)時(shí),后臺(tái)的交互也可能變得非常復(fù)雜。因此,我們需要找到能夠優(yōu)化渲染的直接方法。
從概念上說,我們通常會(huì)碰到兩種類型的更新。第一類是緊急更新,您必須更改輸入字段的值,以及與之相關(guān)的UI。我們可以使用“setInputValue(input); ”來顯示輸入的內(nèi)容。而第二類是不那么緊急的更新--顯示搜索結(jié)果。我們可以使用“setSearchQuery(input); ”來顯示內(nèi)容。
如下代碼段所示,由React 18帶來的新的Transition API,可以對(duì)更新予以標(biāo)記:
JavaScript
- import { startTransition } from 'react';
- // Urgent: Show what was typed
- setInputValue(input);
- // Mark any state updates inside as transitions
- startTransition(() => {
- // Transition: Show the results
- setSearchQuery(input);
- });
小結(jié)
如前所述,由于React 17并不能滿足開發(fā)者社區(qū)的各項(xiàng)需求,因此大家希望作為升級(jí)版的React 18能夠帶來更多新的功能。不過,我們?cè)谏厦嬗懻摰墓δ埽皇菑钠錅y(cè)試版中窺見的特性,也許在發(fā)布之時(shí),其最終版本仍會(huì)有所微調(diào)。當(dāng)然,從目前來看,諸如并發(fā)性等新的功能,足以協(xié)助開發(fā)人員,提高應(yīng)用程序的速度和效率。因此,總的說來React 18是值得我們期待的。
原文標(biāo)題:React 18: Things You Need To Know About React JS Latest Version,作者:Gerrard Cooper
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】