Part5 『入門』Reactポートフォリオ作成(データの設定、取得、表示(詳細ページ))
この記事は、Part4 『入門』Reactポートフォリオ作成の続きになります。
前回のあらすじ
Post.jsでuseStateとuseEffectを使用してsanityからデータを取得しました。
DetailPost.jsでデータ取得の準備
DetailPost.jsはデータを取得して表示することはPost.jsと同じですが、URLにslugを利用して、どの記事の詳細ページなのか判断するためreact-router-domのuseParamsを使用します。
そして記事の画像を扱いやすくするためにsanityから用意されているimage-urlというライブラリもインストールします。
DetailPost.jsを以下のように編集します。
※useState, useEffectは前回のパートで説明済みなので割合します。
/src/components/DetailPost.js
import React, {useState, useEffect} from 'react';
// 追加
import { useParams } from 'react-router-dom';
import sanityClient from '../client';
import imageUrlBuilder from '@sanity/image-url';
// image-url使用↓
const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
return builder.image(source)
}
function DetailPost() {
const [post, setPost] = useState(null);
const { slug } = useParams();
return (
<div>
DetailPost page
</div>
)
}
export default DetailPost
useParams を 'react-router-dom' から読み込み、 const { slug } = useParams(); と書くことで、もしPost.jsの記事がslug Djangoなら{slug: "Django"}の形でDetailPost.jsで取得できるようになり、slugが"Django"の詳細ページのリンクを取得できます。
もちろんsanityからデータを取得するのでPost.jsと同じようにsanityをインポートする必要があります。→ import sanityClient from '../client';
@sanity/image-urlは一言で表すと画像のサイズなどの扱いを簡素化してくれるライブラリです。使用方法は以下で詳しく説明されています。
image-urlをインポートするので、まずはターミナルでインストールコマンドを実行します。
npm install --save @sanity/image-url
これでデータを取得する準備ができました。次はuseEffectで実際に取得していきます。
データの取得
/src/components/DetailPost.js
.
.
.
// 省略
function DetailPost() {
const [post, setPost] = useState(null);
const { slug } = useParams();
// 追加
useEffect(() => {
sanityClient.fetch(`*[slug.current == "${slug}" ]{
title,
_id,
slug,
mainImage{
asset->{
_id,
url
}
},
body,
"name": author->name,
"authImage": author->image
}`
)
.then((data) => setPost(data[0]))
.catch(console.error);
}, [slug]);
return ( )
// 省略
.
.
.
useEffectの基本的な使用はPost.jsと同じですが*[slug.current == "${slug}"は、DetailPostで取得しているslug これ→ (slug.current)とPost.jsで取得したslugが同じなであるなら、title以下の各要素を取得します。
もう一つ新しい点があります。
DetailPostでは記事を書いた人の名前と画像を表示させたいので以下のように書きます。
"name": author->name,
"authImage": author->image
これはauthor->nameと書くことでsanityのauthorモデルのnameを取得することができ好きな名前(key)(nameとauthImage)で値にアクセスできるようになります。
以下の画像は実際にauthorにname: 'name' と name: 'image' が存在するか確認できるように貼り付けました。
/portfolio/schemas/author.js
これでデータの取得ができました。
取得したデータの表示
では、上記で取得したデータを表示していきます。
/src/components/DetailPost.js
// 追加
import BlockContent from '@sanity/block-content-to-react';
.
.
.
// 省略
return (
<div className="detail__post">
<div className="content">
<img
className="main__image"
width="50%"
height="50%"
src={post.mainImage.asset.url}
alt={post.title}
/>
<h3>{post.title}</h3>
<BlockContent
blocks={post.body}
projectId="fccedj7t"
dataset="production"
/>
<div className="user_image">
<img
width="10%"
height="10%"
src={urlFor(post.authImage).width(100).height(100).url()}
alt={post.name}
/>
</div>
</div>
</div>
)
// 省略
.
.
.
まずは、新しく block-content-to-react を BlockContent としてインポートします。
npm install --save @sanity/block-content-to-react
BlockContentについては後で説明します。
postに代入したデータを {post.title} として表示することはPost.jsと同じです。
src={urlFor(post.authImage).url()}はurlFor()関数の引数に画像データを渡すことで容易に画像のリサイズなどが可能になります。
例えば下のように設定します。
<img src={urlFor(post.authImage).width(500).height(300).url()}>
そして、DetailPost.jsの醍醐味でもある <BlockContent />ですが、blocks={post.body} のように記述することで、sanityの管理画面のbodyにデータを投稿する時に文章の間に画像やリスト形式、改行を含めるとその通りにブラウザで表示してくれます。
<BlockContent
blocks={post.body}
projectId="fccedj7t"
dataset="production"
/>
ユーザーの登録
DetailPostでは誰が投稿した記事なのか視覚的にわかるようにするためユーザーの画像を表示します。sanityの管理画面に遷移してauthorを登録します。
①〜⑤の順に登録します。
ユーザーの登録ができるとpostに戻り投稿済みの記事にauthorを追加します。Bodyの内容に改行や文章間に画像を入れてみましょう。
Publishボタンをクリックしたら、ブラウザで確認します。
画像が2分割ですがユーザーの画像もしっかり出力されています。
では最後にCSSで整えます。
CSS見た目を整えよう
/src/index.css
/* Navbar.js */
/* Home.js */
/* About.js */
/* Post.js */
/* DetailPost.js */
.detail__post{
margin-top: 80px;
}
.detail__post > .content > h3{
text-align: center;
font-size: 40px;
color: #5d5b5b;
}
.detail__post > .content > img{
display: block;
border-radius: 5px;
margin: 0 auto;
}
.detail__post > .content > .block__content{
width: 80%;
margin: 0 auto;
}
.detail__post > .content > .block__content > figure {
margin: auto;
}
.detail__post > .content > .block__content > figure > img{
width: 80%;
}
.detail__post > .content > p {
width: 80%;
margin: auto;
}
.detail__post > .content > .user_image{
width: 60%;
display: flex;
margin: 15px auto;
justify-content: flex-end;
align-items: center;
}
.detail__post > .content > .user_image img{
border-radius: 50%;
width: 50px;
}
ブラウザで確認します。
最後に
基本的内容は、このPart5で終了します。
このチュートリアルでは、CMS(sanity)のデータベースを利用してReactで取得するところまで行いました。
しかし、まだまだポートフォリオとしてお問い合わせページやフッター、CSS(デザイン的なもの)レスポンシブなどが十分ではありません。
その辺につきましては、時間がある時に随時更新していきます。