LoginSignup
4
2

More than 3 years have passed since last update.

【React】モーダルごとに別々のOGPを設定する【SPA】

Last updated at Posted at 2020-05-04

やりたいこと

  • webアプリで、画像をモーダルで表示したい!
  • そのモーダルにSNSシェアボタンを設置したい
  • そのモーダルからSNSにシェアすると、その画像がOGPで表示されるようにしたい!
  • ただし、アプリ連携はさせたくない

May-04-2020 20-10-49.gif

image.png

image.png

実装

大まかな説明

  • モーダルを作成
    • material-uiのモーダルを使う
      • 注意1:openは常にtrueにしておく
      • 注意2:onCloseではリダイレクトの関数を実施する
    • モーダルの中にreact-shareの好きなコンポーネントを置く
  • react-helmetでmetaタグを設定する
    • metaタグ設定のコードは、モーダルの横に設置する
  • react-routerでルーティングする(※URLとOGPは1:1対応なので、ルーティングは必須)
  • Netlifyでホスティングする(※自前でprerenderingすれば他のホスティングサービスでも可)
    • Netlifypre-renderingによりSPAでもreact-helmetが機能する
      • 注意1:publicディレクトリ配下に_redirectsファイルを設置しないとreact-routerがうまく動かず、URLが機能しない
      • 注意2:pre-renderingの設定をし忘れない
      • 注意3:ビルドの結果出力されるディレクトリの指定を間違えると、ビルドは成功しても何も表示されない

ライブラリなどのバージョン

バージョンが異なるとコードや動作が異なる場合があります。

  • node v13.11.0
  • react v16.13.1
  • @material-ui/core v4.9.12
  • react-router-dom v5.1.2
  • react-share v4.1.0
  • react-helmet v6.0.0

コード

src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import * as serviceWorker from './serviceWorker';
import {
  BrowserRouter as Router,
  Switch,
  Route,
} from "react-router-dom";
import Lives from './components/Lives';

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <Switch>
        <Route exact path="/">
          <App />
        </Route>
        <Route path="/lives">
          <Lives />
        </Route>
      </Switch>
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);
serviceWorker.unregister();

src/components/Lives.tsx
import React from 'react';
import { useRouteMatch, Link, Switch, Route } from 'react-router-dom';
import { Button } from '@material-ui/core';
import YourModal from './YourModal';

export default function Lives() {
    let { path, url } = useRouteMatch()
    return (
        <div>
            <Switch>
                <Route path={`${path}/:liveId`}>
                    <YourModal />
                </Route>
            </Switch>
            <Link to={`${url}/xxxxxxxxxx`}>
                <Button variant="contained">Open Modal</Button>
            </Link>
        </div>
    )
}
src/components/YourModal.tsx
import React from 'react';
import { useLocation, useHistory } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { Modal } from '@material-ui/core';
import { TwitterShareButton, TwitterIcon } from 'react-share';

export default function YourModal() {
    const baseUrl = "http://example.com"
    const currentUrl: string = baseUrl + useLocation().pathname
    const imgUrl = "https://source.unsplash.com/random"

    const history = useHistory()
    const handleClose = () => {
        history.push("/lives")
    }

    return (
        <div>
            <Helmet
                title={`Lives&Lives`}
                meta={[
                    { name: 'twitter:card', content: 'summary_large_image' },
                    { name: 'twitter:site', content: '@IkkoKojima' },
                    { name: 'twitter:creator', content: '@IkkoKojima' },
                    { property: 'og:title', content: 'Lives&Lives' },
                    { property: 'og:type', content: 'website' },
                    { property: 'og:url', content: currentUrl },
                    { property: 'og:image', content: imgUrl },
                    { property: 'og:description', content: '動物たちのイキイキとした姿をみんなで観察' },
                ]}
            />
            <Modal
                open={true}
                onClose={handleClose}
                style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                }}
            >
                <div style={{ background: 'white' }}>
                    <img src={imgUrl} alt="alt-text" style={{ width: "600px" }} />
                    <TwitterShareButton url={currentUrl} >
                        <TwitterIcon round />
                    </TwitterShareButton>
                </div>
            </Modal>
        </div>
    )
}
public/_redirects
/* /index.html 200

OGP動作確認

この辺が使える。デプロイした後しか動作しないので注意。

最後に

自分用の備忘録として作成したのですごく雑で申し訳ない。なにぶん、数時間ハマった後なので疲れているのです...

不明点や記述のミスなどありましたら、コメントくださいmm

4
2
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
4
2