tamakipedia

鎌倉でフロントエンドエンジニアをしています。Wordpress/Javascript/JQuery が得意で、現在React勉強中です!

【contentful】content field をマークダウン形式に設定する

contentful field というのは、contentful で利用されている入力項目の種類のことです。

こちらでマークダウン形式で入力できるようにフィールドを追加していきます。

手順

1 Add field ボタンでフィールドを追加

2 フィールドの種類は「text」を選択
(「Rich Text」ではないので注意。 )
f:id:okinawanpizza:20211113083726p:plain

3 「Long text」を選択して create and configure を選択
f:id:okinawanpizza:20211113084743p:plain

4 「Appearance」でフィールドの形式を Markdown に変更
f:id:okinawanpizza:20211113084944p:plain

以上

割とすぐ設定できたのでよかった^^

【vercel】【Next.js】vercelを使ってのデプロイ方法

vercelでのデプロイがうまくいかなかったので
最初から作りました。手順メモ。

特に難しくはないのですがポイントが二つあります。
* Create Team は skip すること
* .env.localで設定した環境変数を設定すること

方法

・vercelにアクセスし、下記画像からCreate New Projectを選択。 f:id:okinawanpizza:20211025023257p:plain

・デプロイするリポジトリを選択してimport f:id:okinawanpizza:20211025023430p:plain

・Create Team の設定は Skip を選択 (チームは有料機能なので、
14日間のお試し期間終了後に無料プランで再度デプロイし直すことに、、) f:id:okinawanpizza:20211025025243p:plain

・Environment variables を設定する ここは.env.local で設定した変数を2点入力します。
NAMEにキー、VALUEに値を入力します。

//.env.local
NEXT_PUBLIC_CONTENTFUL_SPACE_ID=xxxxxxxx
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

f:id:okinawanpizza:20211025025329p:plain

・設定完了です。
(スクショが微妙な感じに、、) f:id:okinawanpizza:20211025025427p:plain

以上になります。

5分もかからないでデプロイできるってすごい!!

オブジェクトから値だけを取り出す方法

apiの値を変数に代入する際に、以下のような方法だと可読性が上がります。

const obj = {name: "ko", age: 23, female: true}

const {name, age, female} = obj;

console.log(name); // "ko"

{ var } に代入すると、オブジェクトのキーがvarの値だけを取得できます。

const {name, age, female} = obj;

コンポーネントにpropsを渡すときに、
このモジュール内で使用するapiの値を1行目で確認する役割もあるので便利です。

export default function ArticleDetails({ article }) {
// (ふーん。 サムネとタイトルと記事内容を扱うんだ...)
  const { thumbnail, Title, detail} = article.fields

  return (
    <div>
      <div className="banner">
        <Image 
          src={"https:" + thumbnail.fields.file.url}
          width={thumbnail.fields.file.details.image.width}
          height={thumbnail.fields.file.details.image.height}
          /> 
        <h2>{ Title }</h2>
      </div>
      <div className="detail">
        <h3>detail</h3>
        <div>{ documentToReactComponents(detail) }</div>
      </div>
    </div>
  );
};

おしまい

【contentful】Rich Text を表示するために documentToReactComponents関数 を使う

記事の詳細を作成するときに
記事内容をRich Text で記述するようにしました。
他の項目のようにpropsを渡すだけではなかったので方法を記述します。

contentfulの取得方法はこちら↓ https://okinawanpizza.hatenablog.com/entry/2021/10/21/010930

documentToReactComponents()

contentful側の関数で、リッチテキストの中身を読んでくれる関数のようです。

  • ライブラリをインストール
npm install --save contentful @contentful/rich-text-html-renderer
  • documentToReactComponentsをインポート
import { documentToReactComponents } from '@contentful/rich-text-html-renderer';
  • リッチテキストの項目を引数にして以下のように記述
export default function ArticleDetails({ article }) {
  const {Title, detail} = article.fields

  return (
    <div>
      <div className="detail">
        <h3>detail</h3>
        <div>{ documentToReactComponents(detail) }</div>
      </div>
    </div>
  );
};

これで記事詳細を出力できます。

参考
https://www.contentful.com/developers/docs/javascript/tutorials/rendering-contentful-rich-text-with-javascript/

おしまい

【Next.js】【contentful】動的なルーティングを利用した詳細ページの作成

こんにちは、本日はcontentfulのエントリーの内容を詳細ページに追加していこうと思います。
なお、エントリーは一記事単位の呼び方です。
(下記図参照)

f:id:okinawanpizza:20211024201207p:plain

結果

以下が全体図です。

//pages/posts/[slug].js
import { createClient } from "contentful";
import Image from "next/image";
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"

const client = createClient({
  space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID,
  accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN,
});

export const getStaticPaths = async () => {

  //article 全件取得
  const res = await client.getEntries({
    content_type: "article"
  })

  //全件のパラメーターだけを配列形式で取得
  //[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } } ]
  const paths = res.items.map(item => {
    return {
      params: { slug: item.fields.slug }
    }
  })

  return {
    paths,
    fallback: false
  }
}

export async function getStaticProps({ params }) {
  
  const { items } = await client.getEntries({
    content_type: "article",
    "fields.slug": params.slug
  })

  return{
    props: { article: items[0] }
  }
}


export default function ArticleDetails({ article }) {
  const { thumbnail, Title, detail} = article.fields

  return (
    <div>
      //省略
    </div>
  );
};

Dynamic Routes(動的なルーティング)

Next.jsでは設定したファイル名が自動的にスラッグになります。
また[params].jsなどのようにしてファイル名に角括弧(ブラケット)を使うことで
動的なルーティングを作成できます。

つまり * pages/post/create.js/post/create にマッチします。 * pages/post/[sulg].js/post/1/post/abc にマッチします。

contentfulのインポート

contentfulをインポートします。

import { createClient } from "contentful";

spaceIDとaccessTokenを入力し
contentfulにアクセスするapiを取得します。

const client = createClient({
  space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID,
  accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN,
});

それぞれのエントリーのslug名を全件取得

content_typearticleのエントリー(記事)をjson形式で取得、
それぞれのslugと言う項目だけを返すようにします。
下記のような形が返却されます。
[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } ,....} ]

  //article 全件取得
  const res = await client.getEntries({
    content_type: "article"
  })

  //全件のパラメーターだけを配列形式で取得
  //[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } } ]
  const paths = res.items.map(item => {
    return {
      params: { slug: item.fields.slug }
    }
  })

  return {
    paths,
    fallback: false
  }

ちなみにslugのcontentful側での設定は
content model から手動で設定しているものになります。
f:id:okinawanpizza:20211024214937p:plain

urlに該当するエントリーを取得

現在のurlに該当するエントリーをgetEntries関数で取得し
コンポーネント側にpropsを渡します。

export async function getStaticProps({ params }) {
  
  const { items } = await client.getEntries({
    content_type: "article",
    "fields.slug": params.slug
  })

  return{
    props: { article: items[0] }
  }
}

export default function ArticleDetails({ article }) {
  console.log(article)

  return (
    <div>
      //省略
    </div>
  );
};

以上です!、、思ったより手こずりました。
ただ、youtubeで英語でガッツリ解説してくれている動画を見つけて
そこから意外とスムーズにいきました。

おしまい

【Next.js】getStaticPropsでurlを取得することが可能

//http://localhost:3000/posts/test2

export async function getStaticProps({ params }) {

  console.log(params) // {slug: "test2"}
  
  const { items } = await client.getEntries({
    content_type: "article",
    "fields.slug": params.slug
  })

  return{
    props: { article: items[0] }
  }
}

自分が書いているcontentfulを使ったブログの一部分。

getStaticProps({ params }) を用いるとparamsに{ slug: 'test2' }が格納される。

nextjs.org

useRouterを使わないと取得できないのかと思っていてびっくり。

【Next.js】contentfulのコンテンツをNext.js 側で取得する

contentfulと言うHeadlessCMSで作成した記事内容をNext.js側に出力する方法について。

手順

contentfulをインストール

  • npmでインストール
npm install contentful
  • index.jsxインポート
import { createClient } from "contentful";

データの取得

以下を記述

// index.jsx
export async function getStaticProps() {

  const client = createClient({
    space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID,
    accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN,
  });

  const res = await client.getEntries({content_type: "blog"}); 

  return {
    props: {
      articles: res.items
    }
  }
}

.env.localを作成し以下を記述

NEXT_PUBLIC_CONTENTFUL_SPACE_ID=(①)
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN=(②)

settings→APIkeys→Add API key を押すと下の画像のような画面になるので
space ID と access Token をそれぞれに渡します。
f:id:okinawanpizza:20211024073709p:plain

コンポーネントに渡す

articles: res.itemsと設定しているので、articlesをプロップスとして渡します。

export default function Home({ articles }) {
console.log(articles);
}

以上!