hydrate
hydrate
を使用すると、React 17 以前の react-dom/server
によって事前生成した HTML コンテンツが含まれるブラウザ DOM ノード内に、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 で完全に構築されたアプリには、ルートコンポーネントを引数にした hydrate
呼び出しが通常 1 つのみ存在します。
引数
-
reactNode
: 既存の HTML をレンダーするのに使用される “React ノード”。これは通常、ReactDOM Server
のメソッド(例:React 17 のrenderToString(<App />)
)でレンダーされた JSX である<App />
のようなものです。 -
domNode
: サーバ上でルート要素としてレンダーされた DOM 要素。 -
省略可能
callback
: 関数。渡された場合、React はコンポーネントのハイドレーション後にそれを呼び出します。
返り値
hydrate
は null を返します。
注意点
hydrate
は、レンダーされたコンテンツが、サーバでレンダーされたコンテンツと同一であることを期待しています。React はテキストコンテンツの差異を修正できますが、不一致はバグとして扱い修正する必要があります。- 開発モードでは、React はハイドレーション中の不一致について警告します。不一致が発生した場合、属性の違いが修正される保証はありません。これはパフォーマンス上の理由から重要です。なぜならほとんどのアプリでは、不一致はまれであり、すべてのマークアップを検証することは非常に高コストになるからです。
- アプリには通常、
hydrate
呼び出しは 1 つだけ存在します。フレームワークを使用している場合、フレームワークがこの呼び出しを行うかもしれません。 - アプリがクライアントでレンダーする形式であり、事前レンダーされた 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 では、“ハイドレーション (hydration)” とは、サーバ環境の 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> ); }
これは単一レベルの深さまでしか機能せず、避難ハッチとしての使用を意図しています。過度に使用しないでください。これを使用してもテキストコンテンツ以外の場合は React は違いを修正しようとはしないため、将来の更新まで一貫性が保たれない可能性があります。
クライアントとサーバで異なるコンテンツの処理
サーバとクライアントで意図的に異なるものをレンダーする必要がある場合、2 回に分けたレンダーを行うことができます。クライアントで異なるものをレンダーするコンポーネントは、isClient
のような state 変数を読み取るようにし、この変数をエフェクト内で 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> ); }
この方法では、初回のレンダーはサーバと同じコンテンツをレンダーし、不一致を回避しますが、追加のレンダーがハイドレーションの直後に同期的に行われます。