reactを使って横幅サイズ次第で別のHTMLを出す


なぜやるのか

とあるプロジェクトで、結構厳密なデザインHTMLをBootstrapのレスポンシブで対応を試みた所、かなり期待通りの動きをしないので、Bootstrapを捨ててReactで画面サイズによって見せるHTMLをそもそも変えようと思った。

用意したもの

react(本体)
react-responsive (MediaQuery関係)
react-snap (react プリレンダリング)
ソースはこちら
https://github.com/UG/reactResponsiveTest

PCサイトの見栄え (例)

スマホサイトの見栄え(例)

実際のコード

App.js

import React from 'react';
import './App.css';
import pcsite from './pcsite.jsx'
import smartphone from './smartphon.jsx'

function App() {
  const [size, setSize] = React.useState({ 'width': window.innerWidth, 'height': window.innerHeight });
  window.addEventListener('resize', function () {
    setSize({ 'width': window.innerWidth, 'height': window.innerHeight });
  }, true);
  return (
    <div>
      {size.width > 375 * 2 ? pcsite() : smartphone()}
    </div>
  );
}

export default App;

制御としてはwindow.innerWidthをリサイズ毎にステートセットし直す。 スマホは横幅375*2扱いが多いみたいなので、一旦そこをボーダーにしてみた。

pcsite.jsx

import React from 'react';

export default function pcsite() {
    const test = 'hoge';
    const html = `
    <br>
    <br>
    <br>
    <div class="center">
        <div class="yellowBackground">
            <div class="stepBox">
                <span class="circleStep">1</span>
                <p>test text</p>
            </div>
            <div class="stepBox">
                <span class="circleStep">2</span>
                <p>test text</p>
            </div>
            <div class="stepBox">
                <span class="circleStep">3</span>
                <p>${test}</p>
            </div>
        </div>
    </div>
    `;
    return (
        <div dangerouslySetInnerHTML={{ __html: html }} />
    );
}

reactのdomはHTMLぽいけど、HTMLじゃないので、この様にtemplate stringを使ってHTMLを挿入し、普通のDOMに突っ込むとタグごと出てくるので dangerouslySetInnerHTMLで出力しないとだめらしい。
物々しい名前なのは実際にx-site Scriptingの脆弱性があるから基本使うなという事らしい。
(const使ってれば大丈夫な気がするが、そういう事ではないのか?)

テンプレート文字列にも変数は打ち込めるので、サーバーサイドのテンプレート言語と遜色ないと思う。
スマホHTMLは割愛、ほぼpcsiteと同じ内容で、向いてるCSSが違うとか、全く違うHTMLを書いて構わない。

ハマった点、まだハマり中

  • react-responsiveを使うと、期待した通りの動きができると思ったけど初回しか識別しない模様。
  • PCのブラウザを、DevToolでスマホに変えれば、スマホの方が出てくれる
  • でもブラウザの方をいくら縮めても、スマホという認識をしない。おそらくuser-agentとか色々見てるせい
  • テンプレート文字列にBootstrapを使うと、bootstrap.min.cssをlinkタグで利用すると、CSSがぶっ壊れて描画しなくなるので、共存できないかもしれない。
  • react-bootstrapなるものが存在するが、htmlで div class="sm"とかできない<sm>というタグを使うことになるので、HTML-bootstrapで作った物をreact-bootstrapでそのまま使う事はできない気がする。
  • prerender部分まだエラーが出てちゃんとできてないのでいつかやる。SEO上ゴミだとクライアントが許してくれないと思うので。

そのうち追記するかもです。