您需要知道的有關React 18的新特點
譯文【51CTO.com快譯】業界期待已久的React 18版本終于要發布了。據其團隊透露,他們的React 18 alpha版本及其相關計劃,已經被“安排在路上了”。而根據2019年的一項前端框架調查,React JS已持續被譽為最受歡迎的框架之一。因此,開發人員社區對該框架的期望也在逐年攀升。不過,鑒于React 17的最終版在開發人員社區中,并不太受歡迎。因此,這次React團隊嘗試添加了各種新的特性與功能,并旨在通過首發計劃,來獲取用戶的及時反饋。
從React 18的準備過程我們可以了解到,他們召集了一個由技術專家、代碼庫貢獻者、培訓師、以及開發人員所組成的小組。我從他們在GitHub的討論組處收集到的信息可知,他們通過周密的計劃與開發,希望React 18能夠大放異彩。
React 18的新特性主要涉及到:
- 針對一些重要的開箱即用性能的改進
- 新的并發功能
- 服務器端渲染區域的基礎性改進
在本文中,我將基于自己對于React 18的解釋探索和研究,向您介紹React 18的四個主要新特性。
1. 并發性(Concurrency)
并發性是一種能夠同時執行多項任務的能力。在React 18中,它是作為主要新特性出現的。下面,讓我們來考慮一個標準的React應用場景。假設有一個帶有動畫顯示效果的組件界面。用戶可以輸入或單擊界面上對應的React組件。
其動態效果為:當用戶輸入文字和點擊按鈕時,其對應的動畫效果會在React的上下文處予以呈現。在此過程中,React必須處理所有的函數調用、鉤子調用、以及事件回調,以保證它們可以同時發生。如果React一直把時間花費在渲染動畫幀上,而無法對用戶的輸入做出反應,那么他們就會認為應用程序卡住了。
由于React工作在單線程的進程中,因此它必須合并,重新排序,以及優先處理某些事件和函數,以便為用戶提供最佳、且高質量的使用體驗。對此,React在內部使用到了一個“調度程序”,專門負責對此類回調和請求進行優先級的排序。
可以說,在React 18之前,用戶并不能控制這些函數的調用順序。但是React 18則可以通過Transition API(下文將做詳細討論),向用戶提供對于這類事件循環的各種控制。
2. 自動批處理(Automatic Batching)
從概念上說,為了提高性能,一組React將多個狀態更新放入一次渲染中的操作,被稱為批處理。通常,當同一個點擊事件中帶有兩個、或兩個以上的狀態更新時,那么React會將它們作為一次性的重新渲染(re-render)進行批處理。例如,在如下代碼段正在運行時,當您進行一次單擊時,盡管您在后臺設置為兩個狀態,但是React也只會執行一次性的代碼渲染:
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的批量更新時間并不固定。其原因在于:過去,React只在瀏覽器產生事件(如:用戶的點擊)時,執行批量更新,而此處我們是在事件已經處理之后,才去更新其狀態(如:在fetch的回調中)。請參見如下代碼段:
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引入了自動批處理的方式之后,無論其狀態來自何處,它都會一次性地執行重新渲染。當然,如果您并不想采取批量處理的方式,則可以按照如下代碼段所示,使用Flash同步,來重新渲染目標組件。
3. 讓SSR支持Suspense
在典型的React SSR(服務器端渲染,Server Side Rendering)應用程序中,為了讓服務端直接返回HTML文本給瀏覽器,應用程序通常會發生如下的后臺步驟:
- 服務器檢索那些必須顯示在UI上的相關數據。
- 服務器將整個應用程序渲染為HTML,并將其作為響應傳輸到客戶端。
- 客戶端下載JavaScript包(不包括HTML)。
- 最后,客戶端將JavaScript邏輯連接到HTML上,也就是我們常說的“水合(hydration)”。
當然,典型的SSR應用程序存在著一個問題,即:整個應用程序的每一步,都必須在較短的時間內迅速完成之后,才能開始下一步。 如今的React 18通過Suspense組件,能夠對此類問題進行合理的改進。它會將應用程序分解成為遍歷上述步驟的更小的獨立單元,以便更快地進行交互,并向用戶呈現應用的內容。
4. 轉換(Transition)
作為React 18的一項新功能,Transition API能夠協助用戶解決,在大數據量頁面上出現的頻繁更新的問題。例如,如果需要在已輸入的區域內過濾出數據列表,那么您就必須在對應的狀態中,求解該區域的值,以分離出數據,進而控制輸入進來的字段值。為此,您可以使用“setSearchQuery(input);”來更新輸入值,并搜索結果。
因此,每當有用戶鍵入任何字符時,我們都需要更新輸入值,并使用新的值來查找列表,以最終顯示結果。而當所有的內容都被渲染到大數據量的頁面上時,這可能會導致頁面更新的延遲,從而使其他交互或輸入變得緩慢、甚至無響應。此外,即使您的列表并不太長,用戶在每次擊鍵列表項時,后臺的交互也可能變得非常復雜。因此,我們需要找到能夠優化渲染的直接方法。
從概念上說,我們通常會碰到兩種類型的更新。第一類是緊急更新,您必須更改輸入字段的值,以及與之相關的UI。我們可以使用“setInputValue(input); ”來顯示輸入的內容。而第二類是不那么緊急的更新--顯示搜索結果。我們可以使用“setSearchQuery(input); ”來顯示內容。
如下代碼段所示,由React 18帶來的新的Transition API,可以對更新予以標記:
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);
- });
小結
如前所述,由于React 17并不能滿足開發者社區的各項需求,因此大家希望作為升級版的React 18能夠帶來更多新的功能。不過,我們在上面討論的功能,只是從其測試版中窺見的特性,也許在發布之時,其最終版本仍會有所微調。當然,從目前來看,諸如并發性等新的功能,足以協助開發人員,提高應用程序的速度和效率。因此,總的說來React 18是值得我們期待的。
原文標題:React 18: Things You Need To Know About React JS Latest Version,作者:Gerrard Cooper
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】