はじめに
「Vueはちょくちょく使ってるけど、React触ったことないんだよなぁ」
「Contentful…なんだか今後使う事ありそうだし、使ってみたいなぁ」
そんなフロントエンジニアが、React + Contentful で "おみくじアプリ" を作った際の備忘録です。
やる事
- React導入
- Contentful導入
- つなぎ込み
- 実装
React導入
公式のドキュメント通り
npx create-react-app react-omikuji
で環境が出来ます。(爆速!最高!)
cd react-omikuji
で環境に移動して
npm start
でローカル環境が起動します。
新しい React アプリを作る - React公式ドキュメント
Contentful導入
サインアップ
公式ページからサインアップします。
freeだとユーザー数やAPIコール数に制限がありますが、一旦freeにて。
実案件で使う際は課金が必須になると思います。
スペース作成
今回は omikuji というIDでスペースを作成します。
おみくじ結果の登録
情報として以下が必要になります。
- タイトル (例. 大吉)
- 本文 (例. 最高にハッピーな1日になるでしょう)
なので、上記をコンテントモデルに追加します。
Field IDは
- タイトル => title
- 本文 => description
とします。
続いて、おみくじの結果が複数必要になるので登録していきます。
このような形で6つ、結果を登録します。
つなぎ込み
Contentfulの公式にReactでContentfulを使うチュートリアルがあるので、そちらを参考にReactでContentfulが使えるようつなぎ込みます。
Getting started with React and Contentful - Contentful公式ドキュメント
認証
https://graphql.contentful.com/content/v1/spaces/[YOUR_SPACE_ID]/explore?access_token=[YOUR_ACCESS_TOKEN]
上記に自身のスペースIDとアクセストークンを置き換えアクセスします。
するとGraphiQLの画面になるので、GraphQLクエリを以下の形式で記述します。
{
omikujiCollection {
items {
title
description
}
}
}
エラーがなければ認証完了です。
ReactでContentfulGraphQLを使用する
App.jsを以下に書き換えます。
import {useState, useEffect} from "react";
import './App.css';
const query = `
{
omikujiCollection {
items {
title
description
}
}
}
`
function App() {
const [page, setPage] = useState(null);
useEffect(() => {
window
.fetch(`https://graphql.contentful.com/content/v1/spaces/[YOUR_SPACE_ID]/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer [YOUR_ACCESS_TOKEN]",
},
body: JSON.stringify({ query }),
})
.then((response) => response.json())
.then(({ data, errors }) => {
if (errors) {
console.error(errors);
}
setPage(data.omikujiCollection.items[0]);
});
}, []);
if (!page) {
return "Loading...";
}
return (
<div className="App">
<header className="App-header">
<p>{page.title}</p>
<p>{page.description}</p>
</header>
</div>
);
}
export default App;
これで npm start
をすれば表示されたはずです。
記述の通り0番目の内容が表示されていると思います。
ここまでエラーがなければつなぎ込みは完了です。
実装
仕様の確認
まずどのような仕様のおみくじにするのか確認です。
- トップページ(
react-omikuji/
)で「今日の運勢を占う」ボタンを押下すると、react-omikuji/result
ページに遷移し、結果が表示される - ランダムで結果が表示される
上記が問題なければなんでも良しとします。
ルーティング設定
ページ遷移の挙動を実現するためにreact-router-domをインストールします。
npm i react-router-dom
コンポーネント追加
トップページで使う Button
と、結果ページの Result
のコンポーネントを用意します。
import React from "react";
import { Link } from 'react-router-dom'
export default class Button extends React.Component {
render() {
return (
<Link to="/result">{this.props.text}</Link>
)
}
}
import React from "react";
export default class Result extends React.Component {
render() {
return (
<div>
<p>{this.props.title}</p>
<p>{this.props.description}</p>
<a href="/react-omikuji/">トップに戻る</a>
</div>
)
}
}
実装
App.jsを以下に書き換えます。
import {useState, useEffect} from "react";
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Button from './components/Button';
import Result from './components/Result';
import './App.css';
const query = `
{
omikujiCollection {
items {
title
description
}
}
}
`
function App() {
const [page, setPage] = useState(null);
useEffect(() => {
window
.fetch(`https://graphql.contentful.com/content/v1/spaces/[YOUR_SPACE_ID]/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer [YOUR_ACCESS_TOKEN]",
},
body: JSON.stringify({ query }),
})
.then((response) => response.json())
.then(({ data, errors }) => {
if (errors) {
console.error(errors);
}
const number = Math.floor( Math.random() * ((data.omikujiCollection.items.length - 1) + 1 - 0) ) + 0
setPage(data.omikujiCollection.items[number]);
});
}, []);
if (!page) {
return "Loading...";
}
return (
<div className="App">
<Router basename='/react-omikuji/'>
<Route exact path='/' render={() => <Button text='今日の運勢を占う'/>} />
<Route exact path='/result' render={() => <Result title={page.title} description={page.description}/>} />
</Router>
</div>
);
}
export default App;
ルートディレクトリ変更
トップページを react-omikuji/
とするためにpackage.jsonに以下を追記します。
"homepage": "/react-omikuji/"
完成
npm start
でローカル確認が問題なければ、 npm run build
でビルドされます。
あとがき
「いやいや、おみくじ判定のタイミング!」
「aタグで戻るんかい!」
などなどありますが、あくまで仕様が
- トップページ(
react-omikuji/
)で「今日の運勢を占う」ボタンを押下すると、react-omikuji/result
ページに遷移し、結果が表示される- ランダムで結果が表示される
上記が問題なければなんでも良しとします。
という事で…
トークン丸見え問題・APIコール数問題などなどがあるので、ヘッドレスCMS使うならSSG一択なんでしょうかね…
リンク
新しい React アプリを作る - React公式ドキュメント
Getting started with React and Contentful - Contentful公式ドキュメント