🔖

Reactコンポーネントが吐き出す HTML をいい感じに整形して表示する

2020/09/22に公開1

Reactコンポーネントが吐き出す HTML を React でいい感じに表示するという、とてもピンポイントな記事です。

表示したい元となるコンポーネントを Hoge とします。

const Hoge: React.FC = () => {
  return <div><div>hoge</div><div>fuga</div><p>piyo</p></div>
}

この Hoge がレンダリングするものをインデントなどを整形してシンタックスハイライトまで行って、いい感じに表示します。

Reactコンポーネントの吐き出すHTMLをいい感じに表示する

ちょっと特殊なツールを作りたい人にしか需要がない記事だとは思います。

インストール

npm派のひとは、yarn addnpm i に読み替えてください。

$ yarn add react-highlight.js prettier
$ yarn add @types/prettier @types/react-highlight.js -D

HTMLソースを整形してするために prettier と、シンタックスハイライトするために react-highlight.js をインストールします。

ちなみに、ReactなりNextなりは動いているものとします。

整形する

Reactコンポーネントの吐き出すHTMLを整形します。

import { renderToStaticMarkup } from 'react-dom/server'
import { format } from 'prettier/standalone'
import parserHTML from 'prettier/parser-html'

const formatToHTML = (element: JSX.Element) =>
  format(renderToStaticMarkup(element), {
    parser: 'html',
    plugins: [parserHTML],
  })

renderToStaticMarkupJSX.Element たとえば <Hoge /> の中の HTML をレンダリングして取り出します。

このとき返ってくる文字列は <div><div>hoge</div><div>fuga</div><p>piyo</p></div> です。元々のコンポーネントのソースコードがどういうインデントスタイルであったとしても、余分なインデントや改行を入れることはありません。

そこで、これを人間が読みやすいように、prettier/standaloneformat と、HTML処理用のプラグインとして parserHTML を使います。

その結果、得られるのが、

<div>
  <div>hoge</div>
  <div>fuga</div>
  <p>piyo</p>
</div>

という文字列になります。

さて、Hoge コンポーネントの吐き出すHTMLを、インデント済みのHTMLとして文字列で取得するところまでできました。

次は、シンタックスハイライトです。

シンタックスハイライトする

シンタックスハイライトは簡単です。

import Highlight from 'react-highlight.js'Highlight コンポーネントを読み込んで、<Highlight language="html">{source}</Highlight> のように実行するだけです。

プロパティで JSX.Element を受け取って HTML としてレンダリングする RenderReactHTML というコンポーネントを作ってみましょう。

import Highlight from 'react-highlight.js'
import 'highlight.js/styles/github.css'

type Props = {
  element: JSX.Element
}

const RenderReactHTML: React.FC<Props> = ({ element }) => {
  const source = React.useMemo(() => {
    return formatToHTML(element)
  }, [element])

  return (
    <div>
      <Highlight language="html">{source}</Highlight>
    </div>
  )
}

このコンポーネントは、<RenderReactHTML element={<Hoge />} /> のように使います。

これで、冒頭のスクショのような表示結果が得られます。

Discussion

k-kuraokak-kuraoka

この記事のおかげで困っていたことが解決できました!
ありがとうございます😄