6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React hydrate時の差分検知ではdangerouslySetInnerHTMLで追加した要素は見ない

Posted at

これはなに

React でレンダリングされた DOM にhydrateをする際に、差分があった場合、再レンダリングが行われる。

https://ja.reactjs.org/docs/react-dom.html#hydrate
React はレンダーされる内容が、サーバ・クライアント間で同一であることを期待します。React はテキストコンテンツの差異を修復することは可能ですが、その不一致はバグとして扱い、修正すべきです。開発用モードでは、React は両者のレンダーの不一致について警告します。不一致がある場合に属性の差異が修復されるという保証はありません。これはパフォーマンス上の理由から重要です。なぜなら、ほとんどのアプリケーションにおいて不一致が発生するということは稀であり、全てのマークアップを検証することは許容不可能なほど高コストになるためです。

そう思って、hydrateをしていたところ、再レンダリングがされない場合があったため、その場合の条件と推測を記事にする。

今回、検証を行ったサンプルコードは以下。

どんなときに再レンダリングがされないのか

dangerouslySetInnerHTMLで要素を追加している場合、dangerouslySetInnerHTMLプロパティがついている要素配下で差分が生じていても再レンダリングされないことがわかった。

以下は、サーバーでレンダリングしたときはserver、クライアントでレンダリングしたときはclientと表示されるコンポーネント。

components/App.jsx
import React from "react";

const App = () => {
  let d = "";
  if (typeof window === "undefined") {
    d = "server";
  } else {
    d = "client";
  }

  return (
    <>
      {/* ↓再レンダリングされない */}
      <div
        style={{ backgroundColor: "pink" }}
        dangerouslySetInnerHTML={{ __html: d }}
      ></div>
      {/* ↓再レンダリングされる */}
      <div>{d}</div>
    </>
  );
};

export default App;

↓ が実際の結果のスクリーンショットだが、dangerouslySetInnerHTMLで要素を追加した方(背景がピンク)のみ再レンダリングがされていない。

なぜ再レンダリングされないのか?(推測)

React のソースコードをすべて追いきれなかったので推測になるが、dangerouslySetInnerHTMLのソースを読んでみると、単純にinnerHTMLを読んでいるだけの様。

React が Fiber ツリーをもとにレンダリングしていることを考えると、dangerouslySetInnerHTMLで追加した要素は Fiber ツリーの管理下にないのではないかと思っている(もしくは、dangerouslySetInnerHTML配下は any として扱う)。

その結果、ツリーと実際の DOM を比較しても差分を検出できず、今回のようになってしまう。というのが推測だ。

(もし知っている方がいれば教えていただけるととても助かります!)

最後に

React のソースコードを追いきれず、真の理由を知れなかったのは残念だった。
(React のソースコードを読むのは疲れる。)

もし知っている方がいれば教えていただけるととても助かります!

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?