已棄用

此 API 將在未來 React 主要版本中移除。

在 React 18 中,hydrate 已被 hydrateRoot 替代。在 React 18 中使用 hydrate 會發出警告,提示您的應用程式的行為將與執行 React 17 時一樣。瞭解更多資訊,請訪問 此處

hydrate 允許您在瀏覽器 DOM 節點中顯示 React 元件,該節點的 HTML 內容之前由 React 17 及以下版本的 react-dom/server 生成。

hydrate(reactNode, domNode, callback?)

參考

hydrate(reactNode, domNode, callback?)

在 React 17 及以下版本中呼叫 hydrate,將 React“附加”到已由 React 在伺服器環境中渲染的現有 HTML。

import { hydrate } from 'react-dom';

hydrate(reactNode, domNode);

React 將附加到 domNode 中存在的 HTML,並接管其中 DOM 的管理。完全使用 React 構建的應用程式通常只有一個 hydrate 呼叫及其根元件。

請參閱下面的更多示例。

引數

  • reactNode:用於渲染現有 HTML 的“React 節點”。這通常是像 <App /> 這樣的 JSX 程式碼段,它在 React 17 中使用 ReactDOM Server 方法(如 renderToString(<App />))渲染。

  • domNode:在伺服器上渲染為根元素的 DOM 元素

  • 可選callback:一個函式。如果傳遞,React 將在您的元件完成 hydration 後呼叫它。

返回值

hydrate 會返回 null。

注意事項

  • hydrate 希望渲染的內容與服務端渲染的內容完全相同。React 可以修補文字內容的差異,但你應該將不匹配視為錯誤並修復它們。
  • 在開發模式下,React 會在 hydration 過程中針對不匹配發出警告。但不保證屬性差異會在不匹配的情況下得到修補。這對於效能來說很重要,因為在大多數應用程式中,不匹配的情況很少見,因此驗證所有標記的成本過高。
  • 你的應用程式中很可能只有一個 hydrate 呼叫。如果你使用的是框架,它可能會為你進行此呼叫。
  • 如果你的應用程式是客戶端渲染的,並且沒有預先渲染的 HTML,則不支援使用 hydrate()。請改用 render() (適用於 React 17 及以下版本) 或 createRoot() (適用於 React 18+)。

用法

呼叫 hydrateReact 元件 附加到服務端渲染的 瀏覽器 DOM 節點 中。

import { hydrate } from 'react-dom';

hydrate(<App />, document.getElementById('root'));

不支援使用 hydrate() 來渲染純客戶端應用程式(沒有服務端渲染 HTML 的應用程式)。請改用 render() (在 React 17 及以下版本中) 或 createRoot() (在 React 18+ 中)。

hydrate 服務端渲染的 HTML

在 React 中,“hydration” 是指 React 如何“附加”到已由 React 在服務端環境中渲染的現有 HTML。在 hydration 過程中,React 將嘗試將事件監聽器附加到現有的標記,並在客戶端接管應用程式的渲染。

在完全使用 React 構建的應用程式中,通常只會在啟動時 hydrate 一個“根”元件,一次性完成整個應用程式的 hydrate

import './styles.css';
import { hydrate } from 'react-dom';
import App from './App.js';

hydrate(<App />, document.getElementById('root'));

通常情況下,你不應該再次呼叫 hydrate,也不應該在更多的地方呼叫它。從現在開始,React 將管理應用程式的 DOM。要更新 UI,你的元件將 使用狀態。

有關 hydration 的更多資訊,請參閱 hydrateRoot 的文件。


抑制不可避免的 hydration 不匹配錯誤

如果單個元素的屬性或文字內容在服務端和客戶端之間不可避免地不同(例如,時間戳),則可以抑制 hydration 不匹配警告。

要抑制元素上的 hydration 警告,請新增 suppressHydrationWarning={true}

export default function App() {
  return (
    <h1 suppressHydrationWarning={true}>
      Current Date: {new Date().toLocaleDateString()}
    </h1>
  );
}

這隻在一級深度有效,並且是一個應急方案。不要過度使用它。除非是文字內容,否則 React 仍然不會嘗試修補它,因此它可能會在以後的更新中保持不一致。


處理不同的客戶端和服務端內容

如果你有意需要在服務端和客戶端渲染不同的內容,則可以進行兩次渲染。在客戶端渲染不同內容的元件可以讀取 狀態變數,例如 isClient,你可以在 Effect 中將其設定為 true

import { useState, useEffect } from "react";

export default function App() {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  return (
    <h1>
      {isClient ? 'Is Client' : 'Is Server'}
    </h1>
  );
}

這樣,第一次渲染將渲染與服務端相同的內容,避免不匹配,但在 hydration 之後會立即同步進行第二次渲染。

陷阱

這種方法會降低 hydration 的速度,因為你的元件必須渲染兩次。請注意在網路連線緩慢的情況下的使用者體驗。JavaScript 程式碼的載入時間可能明顯晚於初始 HTML 渲染,因此在 hydration 之後立即渲染不同的 UI 可能會讓使用者感到不適。