Deprecated

この API は、今後のメジャーバージョンの React で削除される予定です。

React 18 では、hydratehydrateRoot に置き換えられました。React 18 で hydrate を使用すると、アプリは React 17 を実行しているかのような振る舞いになるとの警告が表示されます。詳細はこちらをご覧ください。

hydrate を使用すると、React 17 以前で react-dom/server によって以前に生成されたブラウザの DOM ノードの HTML コンテンツ内に React コンポーネントを表示できます。

hydrate(reactNode, domNode, callback?)

リファレンス

hydrate(reactNode, domNode, callback?)

React 17 以前では、hydrate を呼び出して、サーバー環境で既に React がレンダーした既存の HTML に React を「アタッチ」します。

import { hydrate } from 'react-dom';

hydrate(reactNode, domNode);

React は、domNode 内に存在する HTML にアタッチし、その内部の DOM を管理します。React で完全に構築されたアプリは通常、ルートコンポーネントを持つ 1 つの hydrate 呼び出しのみを持ちます。

さらに例を読む

引数

  • reactNode: 既存の HTML をレンダーするのに使用される「React ノード」。これは通常、React 17 における ReactDOM Server のメソッド(例:renderToString(<App />))でレンダーされた JSX の一部である<App />のようなものです。

  • domNode: サーバー上でルート要素としてレンダーされた DOM 要素

  • 省略可能: callback: 関数。渡された場合、React はコンポーネントのハイドレーション後にそれを呼び出します。

返り値

hydrate は null を返します。

注意点

  • hydrate は、レンダーされたコンテンツが、サーバーでレンダーされたコンテンツと同一であることを期待しています。React はテキストコンテンツの差異を修正できますが、不一致はバグとして扱い修正する必要があります。
  • 開発モードでは、React はハイドレーション中の不一致について警告します。不一致が発生した場合、属性の違いが修正される保証はありません。これはパフォーマンス上の理由から重要です。なぜならほとんどのアプリでは、不一致はまれであり、すべてのマークアップを検証することは非常に高コストになるからです。
  • アプリには通常、1 つだけ hydrate 呼び出しが存在するでしょう。フレームワークを使用している場合、フレームワークがこの呼び出しを行うかもしれません。
  • HTML が既にレンダーされていないクライアントレンダリングの場合、hydrate() はサポートされていません。代わりに、React 17 以前では render()、React 18 以降では createRoot() を使用してください。

使用法

hydrate を呼び出して、React コンポーネントをサーバーレンダリングされた ブラウザの DOM ノードにアタッチします。

import { hydrate } from 'react-dom';

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

hydrate() を使用して、クライアントのみのアプリ(サーバーレンダリングされた HTML がないアプリ)をレンダーすることはサポートされていません。代わりに、React 17 以前では render()、React 18 以降では createRoot() を使用してください。

サーバーレンダリングされた HTML のハイドレーション

React では、「ハイドレーション」とは、サーバー環境の React によって既にレンダリングされた既存の HTML に React が「アタッチ」する方法を指します。ハイドレーション中、React は既存のマークアップにイベントリスナをアタッチし、クライアントでアプリをレンダーします。

React で完全に構築されたアプリでは、通常、アプリ全体の起動時に 1 つの「ルート」を一度だけハイドレートします

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

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

通常、hydrate を再度呼び出したり、複数の場所で呼び出したりする必要はありません。ここから先は、React がアプリケーションの DOM を管理しています。UI を更新するには、コンポーネントは state を使うことになるでしょう。

ハイドレーションに関する詳細は、hydrateRoot のドキュメントを参照してください。


やむを得ないハイドレーションの不一致エラーの抑制

サーバーとクライアントの間で、単一の要素の属性やテキストコンテンツがやむを得ない理由で異なる場合(たとえば、タイムスタンプなど)、ハイドレーションの不一致警告を抑制することができます。

要素のハイドレーション警告を抑制するには、suppressHydrationWarning={true} を追加します。

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

これはレベル 1 の深さまでしか機能せず、避難ハッチとしての使用を意図しています。過度に使用しないでください。テキストコンテンツ以外の場合、React はそれを修正しようとはせず、将来の更新まで一貫性が保たれない可能性があります。


クライアントとサーバで異なるコンテンツの処理

サーバとクライアントで意図的に異なるものをレンダーする必要がある場合、2 回のレンダーを行うことができます。クライアントで異なるものをレンダーするコンポーネントは、以下の isClient のような state 変数を読み取ることができます。この変数は、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>
  );
}

この方法では、初回のレンダーはサーバと同じコンテンツをレンダーし、不一致を回避しますが、追加のパスがハイドレーションの直後に同期的に行われます。

落とし穴

このアプローチはハイドレーションを遅くするため、コンポーネントは 2 回レンダーする必要があります。低速な接続の場合、ユーザ体験に注意してください。JavaScript コードは初回の HTML レンダーよりもかなり遅く読み込まれる場合があるため、ユーザにとってハイドレーション直後に異なる UI をレンダーすることは違和感を感じるかもしれません。