ReactJS - hydrateRoot() 方法



使用 React 構建網頁時,我們需要處理伺服器端生成的 HTML 內容。在這種情況下,hydrateRoot 函式非常有用。因此,我們將瞭解 hydrateRoot 是什麼,如何使用它,以及它在某些情況下為什麼很重要。

hydrateRoot 究竟是什麼?

hydrateRoot 是一個 React 方法,允許我們在網頁的 DOM 節點中顯示 React 元件。這個 DOM 節點已經包含了 React 在伺服器端生成的 HTML 內容。或者簡單地說,它允許我們控制 React 已經建立的網頁的一部分,並在客戶端對其進行管理。

const root = hydrateRoot(domNode, reactNode, optionalObject)

簡單來說,當我們在伺服器端(而不是瀏覽器)渲染 React 應用時,它會為我們的元件生成 HTML。然後,hydrateRoot 函式在客戶端使用,以附加事件監聽器並使 HTML 具有互動性。

這個過程稱為“水合”。它將伺服器端渲染的 HTML 與客戶端 JavaScript 相結合,以建立一個完全執行的應用程式。使用 hydrateRoot 有助於 React 最佳化渲染過程並增強使用者體驗。

引數

  • domNode − 為了放置我們的 React 元件,我們必須首先在網頁中建立一個 DOM 元素。此 DOM 元素應該對應於伺服器端渲染內容的根。

  • reactNode − 這是將在 DOM 節點內渲染的 React 元件。它通常是一個 JSX 元素,例如 <App />,它是在伺服器端渲染的。

  • optionalObject − 我們可以提供一個包含附加引數的選項物件。這可以包含一個處理失敗的回撥函式。

hydrateRoot 方法返回一個包含兩個方法的物件:render 和 unmount

render 方法用於更新已水合根內的 React 元件。

root.render(reactNode)

unmount 方法用於銷燬 React 根內的已渲染樹。

root.unmount()

如何使用它?

我們可以透過不同的方式使用 hydrateRoot。第一種是水化整個文件,第二種是處理不同的客戶端和伺服器內容,第三種是更新已水合的根元件。我們將逐一討論這些方法。

示例

示例 − 水化整個文件

建立一個水化整個文件的 React 應用是一個有效的概念。它幫助我們使用 React 元件透過包含 HTML 結構來建立一個完整的網頁。因此,我們將使用此概念建立一個應用 −

  • 使用“npx create-react-app”設定一個 React 應用。

  • 現在我們將為我們的應用建立一個元件。在 src 資料夾內,我們將為應用建立一個名為 App.js 的新元件。

  • 現在,我們將使用 hydrateRoot 函式在 HTML 文件中渲染我們的整個 React 應用。在專案資料夾中,我們有 src/index.js 檔案,因此我們將用下面提到的新程式碼替換現有程式碼。

src/App.js

import React from 'react';

function App() {
   return (
      <html>
         <head>
            <meta charSet="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <link rel="stylesheet" href="/styles.css" />
            <title>My React App</title>
         </head>
         <body>
            <div>
               <h1>Hello, World!</h1>
               <p>This is a simple React app.</p>
            </div>
         </body>
      </html>
   );
}

export default App;

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { hydrateRoot } from 'react-dom/client';

const rootElement = document.getElementById('root');
if (rootElement) {
   hydrateRoot(document, <App />);
} else {
   ReactDOM.render(
      <React.StrictMode>
         <App />
      </React.StrictMode>,
      document.getElementById('root')
   );
}

輸出

simple reactapp

此程式碼塊檢查 rootElement 是否存在。如果存在,它使用 hydrateRoot 將整個文件渲染為一個 React 應用。

示例 − 處理不同的客戶端和伺服器內容

建立一個簡單的應用來演示處理不同客戶端和伺服器內容的這個概念。讓我們看看下面的程式碼 −

  • 首先,我們需要設定一個 React 應用。

  • 現在,我們將建立一個元件,使用兩遍渲染在伺服器和客戶端渲染不同的內容。在 src 資料夾內,我們將為應用建立一個名為 App.js 的元件。

  • 現在,我們將啟動開發伺服器以檢查結果。

src/App.js

import React, { useState, useEffect } from 'react';

function App() {
   const [isClient, setIsClient] = useState(false);   
   useEffect(() => {
      setIsClient(true);
   }, []);   
   return (
   <div>
      <h1>
         {isClient ? 'Rendered on Client' : 'Rendered on Server'}
      </h1>
   </div>
   );
}

export default App;

輸出

rendered on client

在上面的程式碼中,我們有一個狀態變數 isClient,我們使用 useEffect hook 在客戶端將其設定為 true。這讓我們可以根據渲染髮生在伺服器還是客戶端來呈現不同的內容。

示例 − 更新已水合的根元件

我們將建立一個小的 React 應用,顯示一個計數器並每秒重新整理一次以顯示已水合的根元件。這個概念解釋瞭如何使用 root.render 在元件水化後更新它。讓我們看看程式碼 −

  • 首先建立一個新專案,並在終端或命令提示符中導航到我們的專案目錄。

  • 現在我們將修改 src 資料夾中名為 App.js 的 App 元件。現在在這個檔案中,我們將建立一個簡單的計數器 App。在這個檔案中,元件接受一個 counter prop。這個 prop 用於初始化計數器的值。因此,useEffect hook 每秒都會增加應用中的計數器。

  • 現在我們將修改 src/index.js 檔案以使用 hydrateRoot 並每秒更新 App 元件 −

src/App.js

import React, { useState, useEffect } from 'react';

function App({ counter }) {
   const [count, setCount] = useState(counter);   
   useEffect(() => {
   const interval = setInterval(() => {
      setCount(count + 1);
   }, 1000);   
   return () => clearInterval(interval);
   }, [count]);   
   return (
   <div>
      <h1>The Counter: {count}</h1>
      <p>It is updating every second.</p>
   </div>
   );
}

export default App;

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { hydrateRoot } from 'react-dom/client';

const rootElement = document.getElementById('root');

if (rootElement) {
   const root = hydrateRoot(rootElement, <App counter={0} />);   
   let i = 0;
   setInterval(() => {
      root.render(<App counter={i} />);
      i++;
   }, 1000);
} else {
   ReactDOM.render(
      <React.StrictMode>
         <App counter={0} />
      </React.StrictMode>,
      rootElement
   );
}

輸出

the counter 6 updating

此程式碼使用 hydrateRoot 初始化根,然後連續呼叫 root.render 以每秒更新 App 元件,使其計數器值增加。

限制

  • 當我們使用 hydrateRoot 時,它期望我們之前在網頁上顯示的內容與伺服器放置的內容相似。如果它們不匹配,則會出現問題。

  • 如果我們在 React 完成設定(這是水合)之前嘗試更改網頁上的任何內容,React 將刪除所有內容並重新開始。

  • 我們使用 root.unmount 從 React 正在處理的網頁中刪除所有內容。

總結

React 的 hydrateRoot 方法是一種強大的機制,它允許我們在客戶端更新和控制 React 內容,同時確保有效的效能。但是,當我們希望使用動態 React 元件增強伺服器端渲染的 HTML 內容時,通常會使用 hydrateRoot。

reactjs_reference_api.htm
廣告